From 5e87f54fffa9c7e5dccd0ffb14b754bfa339fa9f Mon Sep 17 00:00:00 2001 From: bherbruck Date: Tue, 13 Oct 2026 14:48:19 -0400 Subject: [PATCH] port: surface.plane_p1 (SmPlane part 1, partial) Plane kind of Surface with constructors, evaluation, projection, MakeNurb, DropPointFast, GlobalLineIntersect, TrimPlaneLineToPlaneDomain, CreateIsoParametricCurve, DropCurve, CoincidenceCheck, Reparameterize, ToggleSwapUVBit, RebuildSTEPFromNURBParameters and the re-dispatched SmBSplineSurface methods; C++ shim, ffi binding, difftest runner and fixtures. Wires the UNPORTED(surface.plane_p1) stubs in nurbs.b_spline_surface_p1/p2. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01V8ohWGLCzFPoZriCeSSero --- .../units/surface_curve_bounded_surface.rs | 4 +- crates/difftest/src/units/surface_plane_p1.rs | 1554 ++ .../src/units/surface_surface_cache_p1.rs | 2 +- .../difftest/src/units/surface_surface_p2.rs | 2 +- .../src/units/surface_plane_p1.rs | 691 + crates/solidcore/src/curve/crv_on_surf.rs | 5 + crates/solidcore/src/curve/iso_curve.rs | 5 + .../src/nurbs/b_spline_surface/p1.rs | 15 +- .../src/nurbs/b_spline_surface/p2.rs | 28 +- crates/solidcore/src/surface.rs | 1 + crates/solidcore/src/surface/plane.rs | 10 + crates/solidcore/src/surface/plane/p1.rs | 2241 +++ crates/solidcore/src/surface/surface/p2.rs | 109 +- .../solidcore/src/surface/surface_cache/p1.rs | 20 +- fixtures/surface.plane_p1/upstream.json | 1990 +++ harness/cpp/shim/surface_plane_p1.cpp | 838 + plan/findings.md | 35 + plan/modules.toml | 4 +- reports/difftest/surface.plane_p1.json | 12673 ++++++++++++++++ 19 files changed, 20188 insertions(+), 39 deletions(-) create mode 100644 crates/difftest/src/units/surface_plane_p1.rs create mode 100644 crates/solidcore-ffi/src/units/surface_plane_p1.rs create mode 100644 crates/solidcore/src/surface/plane.rs create mode 100644 crates/solidcore/src/surface/plane/p1.rs create mode 100644 fixtures/surface.plane_p1/upstream.json create mode 100644 harness/cpp/shim/surface_plane_p1.cpp create mode 100644 reports/difftest/surface.plane_p1.json diff --git a/crates/difftest/src/units/surface_curve_bounded_surface.rs b/crates/difftest/src/units/surface_curve_bounded_surface.rs index 83d3902888..af0deb032a 100644 --- a/crates/difftest/src/units/surface_curve_bounded_surface.rs +++ b/crates/difftest/src/units/surface_curve_bounded_surface.rs @@ -778,7 +778,9 @@ fn st(r: solidcore::Result) -> solidcore::Result { fn the_cbs(s: &Surface) -> solidcore::Result<&CurveBoundedSurface> { match s.kind() { SurfaceKind::CurveBounded(c) => Ok(c), - SurfaceKind::BSpline(_) => Err(SolidError::sm_err("difftest: not a curve bounded surface")), + SurfaceKind::BSpline(_) | SurfaceKind::Plane(_) => { + Err(SolidError::sm_err("difftest: not a curve bounded surface")) + } } } diff --git a/crates/difftest/src/units/surface_plane_p1.rs b/crates/difftest/src/units/surface_plane_p1.rs new file mode 100644 index 0000000000..572fed1d1b --- /dev/null +++ b/crates/difftest/src/units/surface_plane_p1.rs @@ -0,0 +1,1554 @@ +//! Runner for unit `surface.plane_p1`: `SmPlane`, part 1. +//! +//! C++: `solidcore_ffi::units::surface_plane_p1` (upstream `source/SMLib/src/SmPlane.cpp` +//! on `SmPlane` objects). Rust: `solidcore::surface::plane`. +//! +//! A case is a plane construction (`make`) and a program of operations (`ops`) run on +//! that plane in order; both sides produce the record documented in the ffi module +//! (statuses `0` = `SM_SUCCESS`, else the `SmStatus`; `1007` for a Rust +//! `InvalidInput`, `-1` for a Rust error upstream cannot produce), reported as the +//! values `rec`. A case whose Rust side reaches an unported unit is deferred as a +//! whole. +//! +//! Deferred cases: `CoincidenceCheck` with a surface that is not a plane +//! (`SmSurface::IsPlanar`, `surface.surface_p7`), `DropCurve` falling back to the +//! general `SmSurface::DropCurve` (`intersect.surface_drop_lib_p3`) and +//! `GlobalLineIntersect` of a line in the plane meeting the domain in one line +//! parameter (`SmSurface::GlobalLineIntersect`, `surface.surface_p8`). + +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +use solidcore::curve::curve::{Curve, CurveKind}; +use solidcore::curve::line::Line; +use solidcore::geom::axis2_placement::Axis2Placement; +use solidcore::geom::extent1d::Extent1d; +use solidcore::geom::extent2d::Extent2d; +use solidcore::geom::global_solver::SolverOperation; +use solidcore::geom::solution_array::{ObjectKind, SolutionArray, SolutionObject, SolutionType}; +use solidcore::geom::vector2d::{Point2, Vec2}; +use solidcore::geom::vector3d::Vec3; +use solidcore::kernel::Kernel; +use solidcore::nurbs::b_spline_curve::BSplineCurve; +use solidcore::nurbs::b_spline_surface::{BSplineSurface, SurfParamType}; +use solidcore::nurbs::math::CPoint; +use solidcore::nurbs::srf_basic::Surface as NurbSurface; +use solidcore::surface::plane::p1::is_grazing_intersection; +use solidcore::surface::plane::Plane; +use solidcore::surface::surface::Surface; +use solidcore::SolidError; +use solidcore_ffi::units::surface_plane_p1::{self as ffi}; + +use crate::case::CaseContext; +use crate::runner::default_cases; +use crate::{Case, HarnessError, Output, Rng, UnitDiff}; + +/// Generated cases per run, whatever `--seeds` says (it can only raise this). +pub const MIN_GENERATED: usize = 1500; + +/// `surface.plane_p1` runner. +pub struct Runner; + +fn harness(msg: impl Into) -> HarnessError { + HarnessError::new(msg) +} + +/// `NL_NOW`. +const NOW: f64 = -f64::MAX; + +// ---- inputs ------------------------------------------------------------------------- + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case", tag = "kind")] +enum MakeIn { + Bounded { + o: [f64; 3], + x: [f64; 3], + y: [f64; 3], + scale: [f64; 2], + domain: [f64; 4], + }, + Normal { + o: [f64; 3], + n: [f64; 3], + }, + Canonical { + o: [f64; 3], + x: [f64; 3], + y: [f64; 3], + }, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +enum DomIn { + Step, + Natural, + Explicit([f64; 4]), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct BSplineCurveIn { + dim: u32, + p: usize, + /// `[x, y, z, w]`; `w` = `null` for a non-rational point. + cpts: Vec<[Option; 4]>, + knots: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case", tag = "kind")] +enum CurveIn { + Segment { a: [f64; 3], b: [f64; 3] }, + BSpline(BSplineCurveIn), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct BSplineSurfaceIn { + p: usize, + q: usize, + /// Rows (u index) of `[x, y, z, w]`; `w` = `null` for a non-rational point. + net: Vec; 4]>>, + u: Vec, + v: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case", tag = "kind")] +enum SurfaceIn { + Plane { make: MakeIn }, + BSpline(BSplineSurfaceIn), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case", tag = "op")] +enum OpIn { + State, + Evaluate { + uv: [f64; 2], + hu: usize, + hv: usize, + #[serde(default)] + upper: bool, + }, + EvalPoint { + uv: [f64; 2], + }, + EvalFast { + uv: [f64; 2], + }, + Normal { + uv: [f64; 2], + }, + Project { + p: [f64; 3], + }, + Queries { + uv: [f64; 2], + }, + KindOf { + t: u32, + }, + Adjust { + dom: DomIn, + }, + MakeNurb, + Reparam { + dom: DomIn, + }, + Toggle, + Rebuild, + Drop { + dom: DomIn, + sop: u8, + p: [f64; 3], + tol: f64, + #[serde(default, skip_serializing_if = "Option::is_none")] + target: Option, + }, + Line { + dom: DomIn, + p: [f64; 3], + v: [f64; 3], + #[serde(default, skip_serializing_if = "Option::is_none")] + ivl: Option<[f64; 2]>, + #[serde(default)] + ray: bool, + tol: f64, + }, + TrimLine { + dom: DomIn, + a: [f64; 3], + b: [f64; 3], + tol: f64, + }, + Iso { + #[serde(default)] + v_dir: bool, + iso: f64, + #[serde(default, skip_serializing_if = "Option::is_none")] + domain: Option<[f64; 4]>, + #[serde(default)] + want_uv: bool, + }, + DropCurve { + dom: DomIn, + curve: CurveIn, + #[serde(default, skip_serializing_if = "Option::is_none")] + ivl: Option<[f64; 2]>, + tol: f64, + #[serde(default)] + keep_all: bool, + #[serde(default)] + creating: bool, + }, + Coincidence { + other: SurfaceIn, + tol: f64, + #[serde(default)] + whole: bool, + }, + Eq { + other: MakeIn, + }, + Copy, + Grazing { + curve: CurveIn, + t: f64, + line: [[f64; 3]; 2], + s: f64, + }, + Inherited { + v: [f64; 3], + }, + Reverse { + #[serde(default)] + v_dir: bool, + }, + Swap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct Inputs { + make: MakeIn, + ops: Vec, +} + +// ---- C++ side --------------------------------------------------------------------- + +fn ffi_make(m: &MakeIn) -> ffi::Make { + match m { + MakeIn::Bounded { + o, + x, + y, + scale, + domain, + } => ffi::Make::Bounded { + o: *o, + x: *x, + y: *y, + scale: *scale, + domain: *domain, + }, + MakeIn::Normal { o, n } => ffi::Make::Normal { o: *o, n: *n }, + MakeIn::Canonical { o, x, y } => ffi::Make::Canonical { + o: *o, + x: *x, + y: *y, + }, + } +} + +fn ffi_dom(d: DomIn) -> ffi::Dom { + match d { + DomIn::Step => ffi::Dom::Step, + DomIn::Natural => ffi::Dom::Natural, + DomIn::Explicit(v) => ffi::Dom::Explicit(v), + } +} + +fn weight(w: Option) -> f64 { + w.unwrap_or(NOW) +} + +fn ffi_curve(c: &CurveIn) -> ffi::CurveIn { + match c { + CurveIn::Segment { a, b } => ffi::CurveIn::Segment(*a, *b), + CurveIn::BSpline(b) => ffi::CurveIn::BSpline(ffi::CurveData { + dim: b.dim, + p: b.p, + cpts: b + .cpts + .iter() + .map(|c| { + [ + c[0].unwrap_or(f64::NAN), + c[1].unwrap_or(f64::NAN), + c[2].unwrap_or(f64::NAN), + weight(c[3]), + ] + }) + .collect(), + knots: b.knots.clone(), + }), + } +} + +fn ffi_surface(s: &SurfaceIn) -> ffi::SurfaceIn { + match s { + SurfaceIn::Plane { make } => ffi::SurfaceIn::Plane(Box::new(ffi_make(make))), + SurfaceIn::BSpline(b) => ffi::SurfaceIn::BSpline(ffi::SurfaceData { + p: b.p, + q: b.q, + net: b + .net + .iter() + .map(|r| { + r.iter() + .map(|c| { + [ + c[0].unwrap_or(f64::NAN), + c[1].unwrap_or(f64::NAN), + c[2].unwrap_or(f64::NAN), + weight(c[3]), + ] + }) + .collect() + }) + .collect(), + u: b.u.clone(), + v: b.v.clone(), + }), + } +} + +fn ffi_op(o: &OpIn) -> ffi::Op { + match o { + OpIn::State => ffi::Op::State, + OpIn::Evaluate { uv, hu, hv, upper } => ffi::Op::Evaluate { + uv: *uv, + hu: *hu, + hv: *hv, + upper: *upper, + }, + OpIn::EvalPoint { uv } => ffi::Op::EvalPoint(*uv), + OpIn::EvalFast { uv } => ffi::Op::EvalFast(*uv), + OpIn::Normal { uv } => ffi::Op::Normal(*uv), + OpIn::Project { p } => ffi::Op::Project(*p), + OpIn::Queries { uv } => ffi::Op::Queries(*uv), + OpIn::KindOf { t } => ffi::Op::KindOf(*t), + OpIn::Adjust { dom } => ffi::Op::Adjust(ffi_dom(*dom)), + OpIn::MakeNurb => ffi::Op::MakeNurb, + OpIn::Reparam { dom } => ffi::Op::Reparam(ffi_dom(*dom)), + OpIn::Toggle => ffi::Op::Toggle, + OpIn::Rebuild => ffi::Op::Rebuild, + OpIn::Drop { + dom, + sop, + p, + tol, + target, + } => ffi::Op::Drop { + dom: ffi_dom(*dom), + op: *sop, + p: *p, + tol: *tol, + target: *target, + }, + OpIn::Line { + dom, + p, + v, + ivl, + ray, + tol, + } => ffi::Op::Line { + dom: ffi_dom(*dom), + p: *p, + v: *v, + ivl: *ivl, + ray: *ray, + tol: *tol, + }, + OpIn::TrimLine { dom, a, b, tol } => ffi::Op::TrimLine { + dom: ffi_dom(*dom), + a: *a, + b: *b, + tol: *tol, + }, + OpIn::Iso { + v_dir, + iso, + domain, + want_uv, + } => ffi::Op::Iso { + v_dir: *v_dir, + iso: *iso, + domain: *domain, + want_uv: *want_uv, + }, + OpIn::DropCurve { + dom, + curve, + ivl, + tol, + keep_all, + creating, + } => ffi::Op::DropCurve { + dom: ffi_dom(*dom), + curve: ffi_curve(curve), + ivl: *ivl, + tol: *tol, + keep_all: *keep_all, + creating: *creating, + }, + OpIn::Coincidence { other, tol, whole } => ffi::Op::Coincidence { + other: ffi_surface(other), + tol: *tol, + whole: *whole, + }, + OpIn::Eq { other } => ffi::Op::Eq(Box::new(ffi_make(other))), + OpIn::Copy => ffi::Op::Copy, + OpIn::Grazing { curve, t, line, s } => ffi::Op::Grazing { + curve: ffi_curve(curve), + t: *t, + line: *line, + s: *s, + }, + OpIn::Inherited { v } => ffi::Op::Inherited(*v), + OpIn::Reverse { v_dir } => ffi::Op::Reverse(*v_dir), + OpIn::Swap => ffi::Op::Swap, + } +} + +fn ffi_program(i: &Inputs) -> (ffi::Make, Vec) { + (ffi_make(&i.make), i.ops.iter().map(ffi_op).collect()) +} + +fn to_output(rec: Vec) -> Output { + Output::new().values("rec", rec) +} + +fn cpp(i: &Inputs) -> Result { + let (m, ops) = ffi_program(i); + match ffi::run(&m, &ops) { + Ok(rec) => Ok(to_output(rec)), + Err(e) => Err(harness(e.to_string())), + } +} + +// ---- Rust side -------------------------------------------------------------------- + +/// The solution handle of plane A (`0`). +#[derive(Debug, Clone, Copy, PartialEq)] +struct H(i64); + +impl SolutionObject for H { + fn kind(&self) -> ObjectKind { + ObjectKind::Surface + } +} + +fn v3(p: [f64; 3]) -> Vec3 { + Vec3::from_array(p) +} + +fn p2(p: [f64; 2]) -> Point2 { + Point2::new(p[0], p[1]) +} + +fn ext(d: [f64; 4]) -> Extent2d { + Extent2d::from_bounds(d[0], d[1], d[2], d[3]) +} + +fn b(x: bool) -> f64 { + if x { + 1.0 + } else { + 0.0 + } +} + +/// The `SmStatus` of a Rust error; `1007` for `InvalidInput`, `-1` for one upstream +/// cannot return. +fn status(e: &SolidError) -> f64 { + match e { + SolidError::InvalidInput { .. } => 1007.0, + SolidError::Upstream { code, .. } => f64::from(*code), + _ => -1.0, + } +} + +/// A failed Rust operation: the whole case is deferred, or the harness failed. +enum Fail { + Deferred(Box), + Harness(HarnessError), +} + +impl From for Fail { + fn from(e: HarnessError) -> Self { + Fail::Harness(e) + } +} + +/// `Ok(v)`, an op status (pushed, `None`), or a deferral. +fn st(o: &mut Vec, r: solidcore::Result) -> Result, Fail> { + match r { + Ok(v) => { + o.push(0.0); + Ok(Some(v)) + } + Err(e) => { + if let Some(d) = Output::unported(&e) { + return Err(Fail::Deferred(Box::new(d))); + } + o.push(status(&e)); + Ok(None) + } + } +} + +fn put_vec(o: &mut Vec, v: Vec3) { + o.extend([v.x, v.y, v.z]); +} + +fn put_uv(o: &mut Vec, v: Vec2) { + o.extend([v.x, v.y]); +} + +fn put_dom(o: &mut Vec, e: &Extent2d) { + o.extend([e.min().x, e.min().y, e.max().x, e.max().y]); +} + +fn put_ivl(o: &mut Vec, e: &Extent1d) { + o.extend([e.min(), e.max()]); +} + +fn put_chars(o: &mut Vec, s: &str) { + o.extend(s.bytes().map(f64::from)); +} + +fn put_surface_nurb(o: &mut Vec, s: Option<&NurbSurface>) { + let Some(sur) = s else { + o.push(0.0); + return; + }; + o.extend([ + 1.0, + sur.n() as f64, + sur.m() as f64, + sur.p() as f64, + sur.q() as f64, + sur.r() as f64, + sur.s() as f64, + ]); + for row in sur.rows() { + for c in row { + o.extend([c.x, c.y, c.z, c.w]); + } + } + o.extend_from_slice(sur.u_knots()); + o.extend_from_slice(sur.v_knots()); +} + +fn put_state(o: &mut Vec, a: &Plane) { + let pos = a.position(); + o.push(a.type_code() as f64); + put_vec(o, pos.origin()); + put_vec(o, pos.x_axis()); + put_vec(o, pos.y_axis()); + put_vec(o, pos.z_axis()); + put_dom(o, &a.step_uv_domain()); + put_uv(o, a.uv_scale()); + let base = a.base(); + o.extend([ + b(base.is_out_of_bounds_enabled()), + f64::from(base.knot_type() as i32), + f64::from(base.form() as i32), + ]); + match a.base_with_nurb() { + Ok(w) => put_surface_nurb(o, w.gw_nurb()), + Err(_) => o.push(0.0), + } +} + +fn put_curve_nurb(o: &mut Vec, c: &BSplineCurve) { + o.extend([f64::from(c.knot_type() as i32), f64::from(c.form() as i32)]); + match c.gw_nurb() { + None => o.push(0.0), + Some(cur) => { + o.extend([1.0, cur.n() as f64, cur.degree() as f64, cur.m() as f64]); + for p in cur.cpts() { + o.extend([p.x, p.y, p.z, p.w]); + } + o.extend_from_slice(cur.knots()); + } + } +} + +fn put_curve(o: &mut Vec, c: &Curve) -> Result<(), Fail> { + o.extend([c.type_code() as f64, c.dim() as f64]); + match c.kind() { + CurveKind::Line(l) => { + put_vec(o, l.line_point()); + put_vec(o, l.line_vector()); + put_ivl(o, &l.step_interval()); + o.extend([l.line_scale(), b(l.inside_out())]); + put_curve_nurb(o, l.base()); + } + CurveKind::BSpline(bs) => put_curve_nurb(o, bs), + _ => return Err(Fail::Harness(harness("unexpected curve kind"))), + } + put_ivl(o, &c.natural_interval()); + Ok(()) +} + +fn put_sols(o: &mut Vec, sols: &SolutionArray) { + o.push(sols.len() as f64); + for s in sols.as_slice() { + let obj0 = if s.num_objects > 0 { + s.objects.first().copied().flatten().map_or(-1.0, |h| h.0 as f64) + } else { + -1.0 + }; + o.extend([ + f64::from(s.solution_type as i32), + s.num_variables as f64, + s.num_objects as f64, + obj0, + s.start.solution_value, + ]); + for k in 0..3 { + o.push(if k < s.num_variables { + s.start.parameters.get(k).copied().unwrap_or(0.0) + } else { + 0.0 + }); + } + let range = s.solution_type == SolutionType::RangeOfValues; + o.push(if range { s.end.solution_value } else { 0.0 }); + for k in 0..3 { + o.push(if range && k < s.num_variables { + s.end.parameters.get(k).copied().unwrap_or(0.0) + } else { + 0.0 + }); + } + } +} + +/// Builds a plane; `Err(status)` when the construction fails. +fn rust_make(m: &MakeIn) -> Result, Fail> { + Ok(match m { + MakeIn::Bounded { + o, + x, + y, + scale, + domain, + } => Ok(Plane::new( + v3(*o), + v3(*x), + v3(*y), + Vec2::new(scale[0], scale[1]), + &ext(*domain), + )), + MakeIn::Normal { o, n } => Ok(Plane::from_normal(v3(*o), v3(*n))), + MakeIn::Canonical { o, x, y } => { + let frame = Axis2Placement::new(v3(*o), v3(*x), v3(*y)); + match Plane::create_canonical(&frame) { + Ok(p) => Ok(p), + Err(e) => { + if let Some(d) = Output::unported(&e) { + return Err(Fail::Deferred(Box::new(d))); + } + Err(status(&e)) + } + } + } + }) +} + +fn other_plane(m: &MakeIn) -> Result { + rust_make(m)?.map_err(|_| Fail::Harness(harness("other plane construction failed"))) +} + +fn dom_of(a: &Plane, d: DomIn) -> Extent2d { + match d { + DomIn::Step => a.step_uv_domain(), + DomIn::Natural => a.natural_uv_domain(), + DomIn::Explicit(v) => ext(v), + } +} + +fn rust_curve(c: &CurveIn) -> Result { + match c { + CurveIn::Segment { a, b } => Line::create_line_segment(3, v3(*a), v3(*b), None) + .map(Curve::from) + .map_err(|e| Fail::Harness(harness(format!("segment: {e}")))), + CurveIn::BSpline(d) => { + let pw: Vec = d + .cpts + .iter() + .map(|q| CPoint { + x: q[0].unwrap_or(f64::NAN), + y: q[1].unwrap_or(f64::NAN), + z: q[2].unwrap_or(f64::NAN), + w: weight(q[3]), + }) + .collect(); + let n = pw.len().checked_sub(1).ok_or_else(|| harness("empty B-spline"))?; + let m = d.knots.len().checked_sub(1).ok_or_else(|| harness("no knots"))?; + BSplineCurve::from_data(u64::from(d.dim), n, m, d.p, &pw, &d.knots) + .map(Curve::from) + .map_err(|e| Fail::Harness(harness(format!("B-spline: {e}")))) + } + } +} + +fn rust_surface(s: &SurfaceIn) -> Result { + match s { + SurfaceIn::Plane { make } => Ok(Surface::from(other_plane(make)?)), + SurfaceIn::BSpline(d) => { + let net = d + .net + .iter() + .map(|r| { + r.iter() + .map(|c| { + CPoint::new( + c[0].unwrap_or(f64::NAN), + c[1].unwrap_or(f64::NAN), + c[2].unwrap_or(f64::NAN), + weight(c[3]), + ) + }) + .collect() + }) + .collect(); + let sur = NurbSurface::new(net, d.p, d.q, d.u.clone(), d.v.clone()) + .map_err(|e| harness(format!("surface: {e}")))?; + Ok(Surface::from(BSplineSurface::from_nurb(sur, false))) + } + } +} + +fn sop(code: u8) -> Result { + SolverOperation::from_code(i32::from(code)).ok_or_else(|| harness("solver operation")) +} + +fn dir(v_dir: bool) -> SurfParamType { + if v_dir { + SurfParamType::V + } else { + SurfParamType::U + } +} + +fn rust_op(k: &Kernel, op: &OpIn, a: &mut Plane, o: &mut Vec) -> Result<(), Fail> { + match op { + OpIn::State => { + o.push(0.0); + put_state(o, a); + } + OpIn::Evaluate { uv, hu, hv, upper } => { + if let Some(d) = st(o, a.evaluate(p2(*uv), *hu, *hv, *upper))? { + for row in &d { + for v in row { + put_vec(o, *v); + } + } + } + } + OpIn::EvalPoint { uv } => { + o.push(0.0); + put_vec(o, a.evaluate_point(p2(*uv))); + } + OpIn::EvalFast { uv } => { + o.push(0.0); + put_vec(o, a.evaluate_point_fast(p2(*uv))); + } + OpIn::Normal { .. } => { + o.push(0.0); + put_vec(o, a.evaluate_normal()); + } + OpIn::Project { p } => { + o.push(0.0); + put_uv(o, a.project_point_to_uv_domain(v3(*p))); + } + OpIn::Queries { .. } => { + o.push(0.0); + o.push(b(a.is_bounded())); + let (pp, pn, dev) = a.is_planar(); + o.push(1.0); + put_vec(o, pp); + put_vec(o, pn); + o.push(dev); + let (seam, sd) = a.is_on_seam(); + o.extend([b(seam), f64::from(sd as i32), 0.0]); + let (closed, ct) = a.is_closed(); + o.extend([b(closed), f64::from(ct as i32)]); + let (s1, d1) = a.is_singularity(); + o.extend([b(s1), f64::from(d1 as i32)]); + let (s2, d2) = a.is_singularity_with_poles(); + o.extend([b(s2), f64::from(d2 as i32)]); + o.push(a.type_code() as f64); + put_chars(o, a.type_string()); + o.push(-1.0); + put_chars(o, a.class_string()); + } + OpIn::KindOf { t } => { + if let Some(x) = st(o, a.is_kind_of(i64::from(*t)))? { + o.push(b(x)); + } + } + OpIn::Adjust { dom } => { + let d = dom_of(a, *dom); + st(o, a.adjust_step_uv_domain(&d))?; + } + OpIn::MakeNurb => { + st(o, a.make_nurb())?; + } + OpIn::Reparam { dom } => { + let d = dom_of(a, *dom); + st(o, a.reparameterize(&d))?; + } + OpIn::Toggle => { + a.toggle_swap_uv_bit(); + o.push(0.0); + } + OpIn::Rebuild => { + st(o, a.rebuild_step_from_nurb_parameters())?; + } + OpIn::Drop { + dom, + sop: code, + p, + tol, + target, + } => { + let d = dom_of(a, *dom); + let r = a.drop_point_fast(&d, sop(*code)?, v3(*p), *tol, *target, Some(H(0))); + if let Some(sols) = st(o, r)? { + put_sols(o, &sols); + } + } + OpIn::Line { + dom, + p, + v, + ivl, + ray, + tol, + } => { + let d = dom_of(a, *dom); + let i = ivl.map(|[x, y]| Extent1d::from_min_max(x, y)); + let r = a.global_line_intersect::(&d, v3(*p), v3(*v), i.as_ref(), *ray, *tol); + if let Some(sols) = st(o, r)? { + put_sols(o, &sols); + } + } + OpIn::TrimLine { dom, a: p0, b: p1, tol } => { + let d = dom_of(a, *dom); + o.push(0.0); + match a.trim_plane_line_to_plane_domain(&d, v3(*p0), v3(*p1), *tol) { + Some((t0, t1)) => { + o.push(1.0); + put_vec(o, t0); + put_vec(o, t1); + } + None => o.push(0.0), + } + } + OpIn::Iso { + v_dir, + iso, + domain, + want_uv, + } => { + let d = domain.map(ext); + let r = a.create_iso_parametric_curve(dir(*v_dir), *iso, d.as_ref(), *want_uv); + if let Some(c) = st(o, r)? { + put_curve(o, &Curve::from(c.curve))?; + o.push(c.max_gap_3d); + match &c.uv_iso_curve { + Some(uv) => { + o.push(1.0); + put_curve(o, uv)?; + } + None => o.push(0.0), + } + } + } + OpIn::DropCurve { + dom, + curve, + ivl, + tol, + keep_all, + creating, + } => { + let d = dom_of(a, *dom); + let c = rust_curve(curve)?; + let i = ivl.map_or_else(|| c.natural_interval(), |[x, y]| Extent1d::from_min_max(x, y)); + let r = a.drop_curve(k, &d, &c, &i, *tol, *keep_all, *creating); + if let Some(res) = st(o, r)? { + o.extend([ + res.max_drop_to_surf, + res.max_approx_dev, + res.uv_curves.len() as f64, + ]); + for c in &res.uv_curves { + put_curve(o, c)?; + } + } + } + OpIn::Coincidence { other, tol, whole } => { + let s = rust_surface(other)?; + if let Some(c) = st(o, a.coincidence_check(k, &s, *tol, *whole))? { + o.extend([b(c.are_coincident), c.max_distance]); + } + } + OpIn::Eq { other } => { + let q = other_plane(other)?; + o.push(0.0); + o.push(b(a.approx_eq(&q))); + } + OpIn::Copy => { + o.push(0.0); + put_state(o, &a.copy()); + } + OpIn::Grazing { curve, t, line, s } => { + let c = rust_curve(curve)?; + let l = Line::create_line_segment(3, v3(line[0]), v3(line[1]), None) + .map_err(|e| harness(format!("segment: {e}")))?; + if let Some(g) = st(o, is_grazing_intersection(&c, *t, &l, *s))? { + o.push(b(g)); + } + } + OpIn::Inherited { v } => { + let s = Surface::from(a.clone()); + o.push(0.0); + put_dom(o, &s.natural_uv_domain()); + let max = s + .max_analytic_domain() + .map_err(|e| harness(format!("max analytic domain: {e}")))?; + put_dom(o, &max); + o.push(b(s.is_bilinear())); + let par = s + .is_parallel_to_vector(v3(*v)) + .map_err(|e| harness(format!("parallel: {e}")))?; + o.push(b(par)); + o.extend([ + s.degree(SurfParamType::U) as f64, + s.degree(SurfParamType::V) as f64, + s.number_control_points(SurfParamType::U) as f64, + s.number_control_points(SurfParamType::V) as f64, + ]); + } + OpIn::Reverse { v_dir } => { + st(o, a.reverse(dir(*v_dir)))?; + } + OpIn::Swap => { + st(o, a.swap_uv())?; + } + } + Ok(()) +} + +fn op_code(op: &OpIn) -> Result { + let prog = ffi::encode( + &ffi::Make::Normal { + o: [0.0; 3], + n: [0.0, 0.0, 1.0], + }, + &[ffi_op(op)], + ) + .map_err(|e| harness(e.to_string()))?; + // `1 o n` (7 values), `1` (op count), then the op code + prog.get(8).copied().ok_or_else(|| harness("empty op")) +} + +fn rust(i: &Inputs) -> Result { + let k = Kernel::default(); + let mut o = Vec::new(); + let made = match rust_make(&i.make) { + Ok(m) => m, + Err(Fail::Deferred(d)) => return Ok(*d), + Err(Fail::Harness(e)) => return Err(e), + }; + let mut a = match made { + Ok(p) => { + o.push(0.0); + p + } + Err(s) => { + o.push(s); + return Ok(to_output(o)); + } + }; + for op in &i.ops { + o.push(op_code(op)?); + match rust_op(&k, op, &mut a, &mut o) { + Ok(()) => {} + Err(Fail::Deferred(d)) => return Ok(*d), + Err(Fail::Harness(e)) => return Err(e), + } + } + put_state(&mut o, &a); + Ok(to_output(o)) +} + +// ---- generated cases -------------------------------------------------------------- + +/// One of `xs`, uniformly. +fn pick(rng: &mut Rng, xs: &[T]) -> T { + let i = rng.below(xs.len() as u64) as usize; + xs.get(i).copied().unwrap_or_default() +} + +fn coord(rng: &mut Rng) -> f64 { + // coordinates on a coarse grid sometimes, so coincidences happen + if rng.chance(0.3) { + rng.range_i64(-4, 4) as f64 + } else { + rng.uniform(-10.0, 10.0) + } +} + +fn pt(rng: &mut Rng) -> [f64; 3] { + [coord(rng), coord(rng), coord(rng)] +} + +fn unit_dir(rng: &mut Rng) -> [f64; 3] { + if rng.chance(0.3) { + // axis aligned + let mut d = [0.0; 3]; + let i = rng.below(3) as usize; + if let Some(c) = d.get_mut(i) { + *c = if rng.chance(0.5) { 1.0 } else { -1.0 }; + } + return d; + } + loop { + let d = rng.point3(-1.0, 1.0); + let l = (d[0] * d[0] + d[1] * d[1] + d[2] * d[2]).sqrt(); + if l > 0.2 { + return [d[0] / l, d[1] / l, d[2] / l]; + } + } +} + +fn cross(a: [f64; 3], b: [f64; 3]) -> [f64; 3] { + [ + a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0], + ] +} + +fn norm(a: [f64; 3]) -> [f64; 3] { + let l = (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]).sqrt(); + [a[0] / l, a[1] / l, a[2] / l] +} + +/// An orthonormal pair (sometimes perturbed, sometimes not unit length). +fn frame(rng: &mut Rng) -> ([f64; 3], [f64; 3]) { + let x = unit_dir(rng); + let mut t = unit_dir(rng); + while cross(x, t).iter().map(|c| c * c).sum::() < 0.05 { + t = unit_dir(rng); + } + let z = norm(cross(x, t)); + let y = cross(z, x); + let mut x = x; + let mut y = y; + if rng.chance(0.15) { + // not unit length + let s = rng.uniform(0.5, 3.0); + x = [x[0] * s, x[1] * s, x[2] * s]; + } + if rng.chance(0.1) { + // not perpendicular + let e = rng.uniform(-0.3, 0.3); + y = [y[0] + e * x[0], y[1] + e * x[1], y[2] + e * x[2]]; + } + (x, y) +} + +fn gen_domain(rng: &mut Rng) -> [f64; 4] { + let u0 = if rng.chance(0.4) { 0.0 } else { rng.uniform(-5.0, 5.0) }; + let v0 = if rng.chance(0.4) { 0.0 } else { rng.uniform(-5.0, 5.0) }; + let du = if rng.chance(0.3) { 1.0 } else { rng.uniform(0.1, 8.0) }; + let dv = if rng.chance(0.3) { 1.0 } else { rng.uniform(0.1, 8.0) }; + [u0, v0, u0 + du, v0 + dv] +} + +fn gen_make(rng: &mut Rng) -> MakeIn { + let r = rng.below(10); + if r < 7 { + let (x, y) = frame(rng); + let scale = if rng.chance(0.4) { + [1.0, 1.0] + } else { + [rng.uniform(0.2, 5.0), rng.uniform(0.2, 5.0)] + }; + MakeIn::Bounded { + o: pt(rng), + x, + y, + scale, + domain: gen_domain(rng), + } + } else if r < 9 { + let n = unit_dir(rng); + let s = rng.uniform(0.3, 4.0); + MakeIn::Normal { + o: pt(rng), + n: [n[0] * s, n[1] * s, n[2] * s], + } + } else { + let (x, y) = frame(rng); + MakeIn::Canonical { o: pt(rng), x, y } + } +} + +/// Approximate geometry of a plane block for building nearby inputs. +struct Geo { + o: [f64; 3], + x: [f64; 3], + y: [f64; 3], + s: [f64; 2], + d: [f64; 4], +} + +impl Geo { + fn of(m: &MakeIn) -> Self { + match m { + MakeIn::Bounded { + o, + x, + y, + scale, + domain, + } => { + let xn = norm(*x); + let z = norm(cross(xn, *y)); + Self { + o: *o, + x: xn, + y: cross(z, xn), + s: *scale, + d: *domain, + } + } + MakeIn::Normal { o, n } => { + let z = norm(*n); + let t = if z[0].abs() < 0.6 { [1.0, 0.0, 0.0] } else { [0.0, 1.0, 0.0] }; + let x = norm(cross(t, z)); + Self { + o: *o, + x, + y: cross(z, x), + s: [1.0, 1.0], + d: [-6.0, -6.0, 6.0, 6.0], + } + } + MakeIn::Canonical { o, x, y } => { + let xn = norm(*x); + let z = norm(cross(xn, *y)); + Self { + o: *o, + x: xn, + y: cross(z, xn), + s: [1.0, 1.0], + d: [-6.0, -6.0, 6.0, 6.0], + } + } + } + } + + fn z(&self) -> [f64; 3] { + norm(cross(self.x, self.y)) + } + + /// The point at relative `(a, b)` of the domain, `h` off the plane. + fn at(&self, a: f64, b: f64, h: f64) -> [f64; 3] { + let u = self.d[0] + a * (self.d[2] - self.d[0]); + let v = self.d[1] + b * (self.d[3] - self.d[1]); + let z = self.z(); + let mut p = [0.0; 3]; + for (i, c) in p.iter_mut().enumerate() { + let g = |w: &[f64; 3]| w.get(i).copied().unwrap_or(0.0); + *c = g(&self.o) + u * self.s[0] * g(&self.x) + v * self.s[1] * g(&self.y) + h * g(&z); + } + p + } + + fn uv(&self, rng: &mut Rng) -> [f64; 2] { + let a = rng.uniform(-0.3, 1.3); + let b = rng.uniform(-0.3, 1.3); + [ + self.d[0] + a * (self.d[2] - self.d[0]), + self.d[1] + b * (self.d[3] - self.d[1]), + ] + } +} + +fn gen_rel(rng: &mut Rng) -> f64 { + if rng.chance(0.2) { + pick(rng, &[0.0, 1.0, 0.5]) + } else { + rng.uniform(-0.4, 1.4) + } +} + +fn gen_dom(rng: &mut Rng, g: &Geo) -> DomIn { + match rng.below(4) { + 0 | 1 => DomIn::Step, + 2 => DomIn::Natural, + _ => { + let a = rng.uniform(-0.2, 0.6); + let c = rng.uniform(-0.2, 0.6); + let w = g.d[2] - g.d[0]; + let h = g.d[3] - g.d[1]; + DomIn::Explicit([ + g.d[0] + a * w, + g.d[1] + c * h, + g.d[0] + (a + rng.uniform(0.2, 0.8)) * w, + g.d[1] + (c + rng.uniform(0.2, 0.8)) * h, + ]) + } + } +} + +fn gen_bspline_curve(rng: &mut Rng, g: &Geo, height: f64) -> BSplineCurveIn { + let p = 1 + rng.below(3) as usize; + let n1 = p + 1 + rng.below(3) as usize; + let rational = rng.chance(0.25); + let cpts = (0..n1) + .map(|_| { + let q = g.at(rng.uniform(0.1, 0.9), rng.uniform(0.1, 0.9), rng.uniform(-height, height)); + let w = if rational { Some(rng.uniform(0.5, 2.0)) } else { None }; + [Some(q[0]), Some(q[1]), Some(q[2]), w] + }) + .collect(); + let interior = n1 - p - 1; + let mut knots = vec![0.0; p + 1]; + for i in 0..interior { + knots.push((i + 1) as f64 / (interior + 1) as f64); + } + knots.extend(vec![1.0; p + 1]); + BSplineCurveIn { + dim: 3, + p, + cpts, + knots, + } +} + +fn gen_curve(rng: &mut Rng, g: &Geo) -> CurveIn { + if rng.chance(0.5) { + let h = if rng.chance(0.5) { 0.0 } else { rng.uniform(-1.0, 1.0) }; + let a = g.at(gen_rel(rng), gen_rel(rng), h); + let mut b = g.at(gen_rel(rng), gen_rel(rng), if rng.chance(0.5) { h } else { rng.uniform(-1.0, 1.0) }); + if a == b { + b[0] += 1.0; + } + CurveIn::Segment { a, b } + } else { + let h = if rng.chance(0.4) { 0.0 } else { rng.uniform(0.0, 0.5) }; + CurveIn::BSpline(gen_bspline_curve(rng, g, h)) + } +} + +fn gen_other(rng: &mut Rng, m: &MakeIn, g: &Geo) -> SurfaceIn { + if rng.chance(0.15) { + // a bilinear patch near the plane (not an SmPlane) + let net = (0..2) + .map(|i| { + (0..2) + .map(|j| { + let q = g.at(f64::from(i), f64::from(j), 0.0); + [Some(q[0]), Some(q[1]), Some(q[2]), None] + }) + .collect() + }) + .collect(); + return SurfaceIn::BSpline(BSplineSurfaceIn { + p: 1, + q: 1, + net, + u: vec![0.0, 0.0, 1.0, 1.0], + v: vec![0.0, 0.0, 1.0, 1.0], + }); + } + let make = match rng.below(5) { + 0 => m.clone(), + 1 | 2 => { + // coplanar, shifted / scaled domain + let (o, x, y) = (g.o, g.x, g.y); + let mut d = g.d; + let su = (d[2] - d[0]) * rng.uniform(-1.2, 1.2); + let sv = (d[3] - d[1]) * rng.uniform(-1.2, 1.2); + d = [d[0] + su, d[1] + sv, d[2] + su * rng.uniform(0.5, 1.5), d[3] + sv]; + if d[2] <= d[0] { + d[2] = d[0] + 1.0; + } + let (x, y) = if rng.chance(0.3) { (y, [-x[0], -x[1], -x[2]]) } else { (x, y) }; + MakeIn::Bounded { + o, + x, + y, + scale: g.s, + domain: d, + } + } + 3 => { + // offset or tilted + let z = g.z(); + let h = if rng.chance(0.5) { 1e-8 } else { rng.uniform(-1.0, 1.0) }; + let o = [g.o[0] + h * z[0], g.o[1] + h * z[1], g.o[2] + h * z[2]]; + let tilt = if rng.chance(0.5) { 0.0 } else { rng.uniform(-0.2, 0.2) }; + let x = norm([g.x[0] + tilt * z[0], g.x[1] + tilt * z[1], g.x[2] + tilt * z[2]]); + MakeIn::Bounded { + o, + x, + y: g.y, + scale: g.s, + domain: g.d, + } + } + _ => gen_make(rng), + }; + SurfaceIn::Plane { make } +} + +fn gen_op(rng: &mut Rng, m: &MakeIn, g: &Geo, nurb_safe: bool) -> OpIn { + let r = rng.below(27); + match r { + 0 => OpIn::State, + 1 | 2 => { + let hu = rng.below(4) as usize; + let hv = rng.below(4) as usize; + let upper = hu <= hv && rng.chance(0.3); + OpIn::Evaluate { + uv: g.uv(rng), + hu, + hv, + upper, + } + } + 3 => OpIn::EvalPoint { uv: g.uv(rng) }, + 4 => OpIn::EvalFast { uv: g.uv(rng) }, + 5 => OpIn::Normal { uv: g.uv(rng) }, + 6 => OpIn::Project { + p: g.at(gen_rel(rng), gen_rel(rng), rng.uniform(-3.0, 3.0)), + }, + 7 => OpIn::Queries { uv: g.uv(rng) }, + 8 => OpIn::KindOf { + t: pick(rng, &[15011, 15002, 15001, 15013, 1, 0, 3]), + }, + 9 => OpIn::Adjust { dom: gen_dom(rng, g) }, + 11 => OpIn::Reparam { + dom: DomIn::Explicit(gen_domain(rng)), + }, + 12 if nurb_safe => OpIn::Toggle, + 13 => OpIn::Rebuild, + 14 | 15 => { + let sop = pick(rng, &[3u8, 5, 0, 4, 1]); + let h = if rng.chance(0.3) { 0.0 } else { rng.uniform(-2.0, 2.0) }; + OpIn::Drop { + dom: gen_dom(rng, g), + sop, + p: g.at(gen_rel(rng), gen_rel(rng), h), + tol: pick(rng, &[1e-6, 1e-3, 0.5, 3.0]), + target: rng.chance(0.3).then(|| rng.uniform(0.0, 3.0)), + } + } + 16 | 17 => { + let p = g.at(gen_rel(rng), gen_rel(rng), if rng.chance(0.3) { 0.0 } else { rng.uniform(-3.0, 3.0) }); + let v = if rng.chance(0.3) { + // in the plane + let a = rng.uniform(-1.0, 1.0); + let c = rng.uniform(-1.0, 1.0); + [ + a * g.x[0] + c * g.y[0], + a * g.x[1] + c * g.y[1], + a * g.x[2] + c * g.y[2], + ] + } else { + unit_dir(rng) + }; + let v = if v.iter().all(|c| c.abs() < 1e-3) { g.z() } else { v }; + OpIn::Line { + dom: gen_dom(rng, g), + p, + v, + ivl: rng.chance(0.4).then(|| { + let a = rng.uniform(-5.0, 2.0); + [a, a + rng.uniform(0.5, 8.0)] + }), + ray: rng.chance(0.25), + tol: pick(rng, &[1e-6, 1e-3, 0.5]), + } + } + 18 => { + let h = if rng.chance(0.5) { 0.0 } else { rng.uniform(-1.0, 1.0) }; + OpIn::TrimLine { + dom: gen_dom(rng, g), + a: g.at(gen_rel(rng), gen_rel(rng), h), + b: g.at(gen_rel(rng), gen_rel(rng), h), + tol: pick(rng, &[0.0, 1e-6, 0.1]), + } + } + 19 => { + let v_dir = rng.chance(0.5); + let (lo, hi) = if v_dir { (g.d[1], g.d[3]) } else { (g.d[0], g.d[2]) }; + OpIn::Iso { + v_dir, + iso: lo + rng.uniform(-0.2, 1.2) * (hi - lo), + domain: rng.chance(0.3).then(|| gen_domain(rng)), + want_uv: rng.chance(0.5), + } + } + 20 | 21 => { + let curve = gen_curve(rng, g); + OpIn::DropCurve { + dom: gen_dom(rng, g), + curve, + ivl: rng.chance(0.3).then(|| { + let a = rng.uniform(0.0, 0.4); + [a, a + rng.uniform(0.2, 0.6)] + }), + tol: pick(rng, &[1e-6, 1e-3, 0.3, 2.0]), + keep_all: rng.chance(0.5), + creating: rng.chance(0.3), + } + } + 22 | 23 => OpIn::Coincidence { + other: gen_other(rng, m, g), + tol: pick(rng, &[1e-6, 1e-3, 0.1]), + whole: rng.chance(0.4), + }, + 24 if nurb_safe => OpIn::Eq { + other: if rng.chance(0.5) { m.clone() } else { gen_make(rng) }, + }, + 10 | 12 | 24 => OpIn::MakeNurb, + 25 => { + if rng.chance(0.5) { + OpIn::Copy + } else { + OpIn::Inherited { + v: if rng.chance(0.5) { g.x } else { unit_dir(rng) }, + } + } + } + _ => { + if rng.chance(0.15) { + // a quadratic tangent to the line at its start: a graze + let p0 = g.at(gen_rel(rng), gen_rel(rng), 0.0); + let p1 = g.at(gen_rel(rng), gen_rel(rng), 0.0); + let p2 = g.at(gen_rel(rng), gen_rel(rng), rng.uniform(-1.0, 1.0)); + let mut l1 = [2.0 * p1[0] - p0[0], 2.0 * p1[1] - p0[1], 2.0 * p1[2] - p0[2]]; + if l1 == p0 { + l1[0] += 1.0; + } + let cp = |q: [f64; 3]| [Some(q[0]), Some(q[1]), Some(q[2]), None]; + OpIn::Grazing { + curve: CurveIn::BSpline(BSplineCurveIn { + dim: 3, + p: 2, + cpts: vec![cp(p0), cp(p1), cp(p2)], + knots: vec![0.0, 0.0, 0.0, 1.0, 1.0, 1.0], + }), + t: 0.0, + line: [p0, l1], + s: 0.0, + } + } else if rng.chance(0.4) { + let c = gen_curve(rng, g); + let l0 = g.at(gen_rel(rng), gen_rel(rng), 0.0); + let mut l1 = g.at(gen_rel(rng), gen_rel(rng), 0.0); + if l0 == l1 { + l1[0] += 1.0; + } + OpIn::Grazing { + curve: c, + t: rng.uniform(0.0, 1.0), + line: [l0, l1], + s: rng.uniform(0.0, 1.0), + } + } else if rng.chance(0.5) { + OpIn::Reverse { + v_dir: rng.chance(0.5), + } + } else { + OpIn::Swap + } + } + } +} + +fn gen_case(rng: &mut Rng) -> Inputs { + let make = gen_make(rng); + let g = Geo::of(&make); + let n = 1 + rng.below(5) as usize; + // A NURB upstream makes lazily in a const method (or a copy) stays with the plane; + // the port makes it on a copy. ToggleSwapUVBit (which leaves the NURB alone) and + // operator== (which compares NURBs) observe the difference, so they come only + // while both sides agree: before any such method or once the NURB is made in place. + let mut made = matches!(make, MakeIn::Canonical { .. }); + let mut lazy = false; + let mut ops = Vec::with_capacity(n); + for _ in 0..n { + let op = gen_op(rng, &make, &g, made || !lazy); + match &op { + OpIn::MakeNurb + | OpIn::Reparam { .. } + | OpIn::Rebuild + | OpIn::Reverse { .. } + | OpIn::Swap => made = true, + OpIn::Coincidence { .. } | OpIn::Iso { .. } | OpIn::Copy => lazy = true, + OpIn::Drop { sop, .. } if *sop == 5 => lazy = true, + _ => {} + } + ops.push(op); + } + Inputs { make, ops } +} + +impl UnitDiff for Runner { + fn id(&self) -> &'static str { + "surface.plane_p1" + } + + fn generate(&self, rng: &mut Rng) -> Option { + for _ in 0..64 { + let i = gen_case(rng); + let (m, ops) = ffi_program(&i); + if ffi::encode(&m, &ops).is_ok() { + return serde_json::to_value(i).ok(); + } + } + None + } + + fn cases(&self, ctx: &CaseContext) -> Result, HarnessError> { + let ctx = CaseContext { + seeds: ctx.seeds.max(MIN_GENERATED), + ..ctx.clone() + }; + default_cases(self, &ctx) + } + + fn run_cpp(&self, case: &Case) -> Result { + cpp(&case.parse()?) + } + + fn run_rust(&self, case: &Case) -> Result { + rust(&case.parse()?) + } +} + diff --git a/crates/difftest/src/units/surface_surface_cache_p1.rs b/crates/difftest/src/units/surface_surface_cache_p1.rs index 7d6496dc2a..1b5e9ccd1c 100644 --- a/crates/difftest/src/units/surface_surface_cache_p1.rs +++ b/crates/difftest/src/units/surface_surface_cache_p1.rs @@ -1112,7 +1112,7 @@ fn rust_op(i: &Inputs) -> Result { ProgIn::FirstPatch { node } => { let own = match cache.surface().kind() { SurfaceKind::BSpline(b) => b.gw_nurb(), - SurfaceKind::CurveBounded(_) => None, + SurfaceKind::CurveBounded(_) | SurfaceKind::Plane(_) => None, }; match cache.first_bezier_patch(NodeId(*node)) { Ok(None) => o.push(0.0), diff --git a/crates/difftest/src/units/surface_surface_p2.rs b/crates/difftest/src/units/surface_surface_p2.rs index d96309b23a..b3228f5abe 100644 --- a/crates/difftest/src/units/surface_surface_p2.rs +++ b/crates/difftest/src/units/surface_surface_p2.rs @@ -1077,7 +1077,7 @@ fn dump_state(o: &mut Vec, s: Option<&Surface>) { match s.map(Surface::kind) { Some(sp2::SurfaceKind::BSpline(b)) => dump_bss(o, b), // `put_state` of a surface that is not a B-spline - Some(sp2::SurfaceKind::CurveBounded(_)) | None => o.push(0.0), + Some(sp2::SurfaceKind::CurveBounded(_) | sp2::SurfaceKind::Plane(_)) | None => o.push(0.0), } } diff --git a/crates/solidcore-ffi/src/units/surface_plane_p1.rs b/crates/solidcore-ffi/src/units/surface_plane_p1.rs new file mode 100644 index 0000000000..d5f3b1148c --- /dev/null +++ b/crates/solidcore-ffi/src/units/surface_plane_p1.rs @@ -0,0 +1,691 @@ +//! FFI wrappers for unit `surface.plane_p1`. +//! +//! Shim: `harness/cpp/shim/surface_plane_p1.cpp` (`sc_surface_plane_p1_run`). Upstream: +//! `source/SMLib/src/SmPlane.cpp`, `source/SMLib/inc/SmPlane.h` (`SmPlane`). +//! +//! [`run`] builds plane A from a [`Make`], runs the [`Op`]s on it in order and returns +//! the record `make_status`, then per op `op status [values]` (values only for status +//! 0), then the state of A (nothing after a failed construction). Statuses are `0` +//! (`SM_SUCCESS`) or the `SmStatus`. +//! +//! A plane state is `type O[3] X[3] Y[3] Z[3] domain[4] scale[2] oob knot_type form` +//! then the NURB `has [n m p q r s cpts(x y z w) u v]` (the plane's, or the one a copy +//! makes when it has none). A curve is `type dim [P[3] V[3] dom[2] scale inside_out]` +//! (the bracket for lines) then `knot_type form has [n p m cpts(x y z w) knots]` and the +//! natural interval. Solutions are `count` then per solution `type nvars nobjs obj0 +//! start_value start[3] end_value end[3]` (objects: `0` = A, `1` = another, `-1` = +//! none; unused parameters and the end of a single value are `0`). +//! +//! | [`Op`] | upstream | values | +//! |-----------------|-----------------------------------------------|--------| +//! | `State` | getters | state | +//! | `Evaluate` | `Evaluate(uv, hu, hv, TRUE, TRUE, upper)` | `(hu+1)(hv+1)` vectors, `D[i][j]` row by row | +//! | `EvalPoint`, `EvalFast` | `EvaluatePoint`, `EvaluatePointFast` | point | +//! | `Normal` | `EvaluateNormal(uv, TRUE, TRUE)` | vector | +//! | `Project` | `ProjectPointToUVDomain` | uv | +//! | `Queries` | `IsBounded`, `IsPlanar`, `IsOnSeam`, `IsClosed`, both `IsSingularity`, `GetType`, `GetTypeString`, `GetClassString` | values, type chars, `-1`, class chars | +//! | `KindOf` | `IsKindOf` | flag | +//! | `Adjust`, `MakeNurb`, `Reparam`, `Toggle`, `Rebuild`, `Reverse`, `Swap` | `AdjustSTEPUVDomain`, `MakeNurb`, `Reparameterize`, `ToggleSwapUVBit`, `RebuildSTEPFromNURBParameters`, `Reverse`, `SwapUV` | | +//! | `Drop` | `DropPointFast(dom, op, p, NULL, tol, target, SM_SR_ALL)` | solutions | +//! | `Line` | `GlobalLineIntersect` | solutions | +//! | `TrimLine` | `TrimPlaneLineToPlaneDomain` | `found [start end]` | +//! | `Iso` | `CreateIsoParametricCurve` | curve, gap, `has [uv curve]` | +//! | `DropCurve` | `DropCurve` | `max_drop max_dev count curves` | +//! | `Coincidence` | `CoincidenceCheck` | `flag max_dist` | +//! | `Eq` | `operator==` | flag | +//! | `Copy` | `Copy` | state | +//! | `Grazing` | `sm_IsGrazingIntersection` (file static, copied into the shim) | flag | +//! | `Inherited` | of a copy: `GetNaturalUVDomain`, `GetMaxAnalyticDomain`, `IsBilinear`, `IsParallelToVector(v)`, `GetDegree` and `GetNumberControlPoints` (u, v) | values | +//! +//! [`run`] accepts only finite inputs of magnitude at most [`MAX_COORD`], well-formed +//! clamped B-splines (at most [`MAX_INDEX`] + 1 control points per direction, degree +//! at most [`MAX_DEGREE`], positive weights or none) and at most [`MAX_OPS`] ops. + +use crate::{call_with_buffer, FfiError}; + +mod sys { + extern "C" { + pub fn sc_surface_plane_p1_run( + input: *const f64, + n_in: i64, + out: *mut f64, + cap: i64, + out_len: *mut i64, + ) -> i32; + } +} + +/// Largest control point index `n` (curves: 32, surfaces: 16 per direction). +pub const MAX_INDEX: usize = 16; +/// Largest degree. +pub const MAX_DEGREE: usize = 8; +/// Largest input magnitude. +pub const MAX_COORD: f64 = 1e9; +/// Most ops per program. +pub const MAX_OPS: usize = 64; +/// `NL_NOW`: the weight of a non-rational control point. +pub const NOW: f64 = -f64::MAX; + +/// How plane A (or another plane) is built. +#[derive(Debug, Clone, PartialEq)] +pub enum Make { + /// `SmPlane(o, x, y, SmVector2d(scale), SmExtent2d(domain), ctx)`. + Bounded { + /// Origin. + o: [f64; 3], + /// X axis. + x: [f64; 3], + /// Y axis. + y: [f64; 3], + /// u and v scales. + scale: [f64; 2], + /// `umin vmin umax vmax`, stored as given. + domain: [f64; 4], + }, + /// `SmPlane(o, normal, ctx)`. + Normal { + /// Origin. + o: [f64; 3], + /// Normal. + n: [f64; 3], + }, + /// `SmPlane::CreateCanonical(ctx, SmAxis2Placement(o, x, y), p)`. + Canonical { + /// Origin. + o: [f64; 3], + /// X axis. + x: [f64; 3], + /// Y axis. + y: [f64; 3], + }, +} + +/// A domain operand. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Dom { + /// `GetSTEPUVDomain()` at op time. + Step, + /// `SmExtent2d(umin, vmin, umax, vmax)`. + Explicit([f64; 4]), + /// `GetNaturalUVDomain()` of a copy at op time. + Natural, +} + +/// A clamped B-spline curve: `SmBSplineCurve(dim, n, m, p, Pw, U)`. +#[derive(Debug, Clone, PartialEq)] +pub struct CurveData { + /// Image dimension, 2 or 3. + pub dim: u32, + /// Degree. + pub p: usize, + /// Control points as stored (`x y z w`, `w` = [`NOW`] when non-rational). + pub cpts: Vec<[f64; 4]>, + /// Knots (`n + p + 2` of them). + pub knots: Vec, +} + +/// A curve operand. +#[derive(Debug, Clone, PartialEq)] +pub enum CurveIn { + /// `SmLine::CreateLineSegment(ctx, 3, a, b, l)`. + Segment([f64; 3], [f64; 3]), + /// A B-spline curve. + BSpline(CurveData), +} + +/// A clamped B-spline surface: `SmBSplineSurface(gw_SURFACE*, FALSE, ctx)`. +#[derive(Debug, Clone, PartialEq)] +pub struct SurfaceData { + /// u degree. + pub p: usize, + /// v degree. + pub q: usize, + /// Control net, row `i` (u index) of `x y z w` points. + pub net: Vec>, + /// u knots. + pub u: Vec, + /// v knots. + pub v: Vec, +} + +/// The other surface of a coincidence test. +#[derive(Debug, Clone, PartialEq)] +pub enum SurfaceIn { + /// A plane. + Plane(Box), + /// A B-spline surface. + BSpline(SurfaceData), +} + +/// One operation on plane A. +#[derive(Debug, Clone, PartialEq)] +pub enum Op { + /// The state of A. + State, + /// `Evaluate(uv, hu, hv, TRUE, TRUE, upper)`. + Evaluate { + /// Parameter. + uv: [f64; 2], + /// Highest u derivative (at most 4). + hu: usize, + /// Highest v derivative (at most 4). + hv: usize, + /// Upper half only (requires `hu <= hv`). + upper: bool, + }, + /// `EvaluatePoint(uv)`. + EvalPoint([f64; 2]), + /// `EvaluatePointFast(uv)`. + EvalFast([f64; 2]), + /// `EvaluateNormal(uv, TRUE, TRUE)`. + Normal([f64; 2]), + /// `ProjectPointToUVDomain(p)`. + Project([f64; 3]), + /// The simple queries at `uv`. + Queries([f64; 2]), + /// `IsKindOf(t)`. + KindOf(u32), + /// `AdjustSTEPUVDomain(dom)`. + Adjust(Dom), + /// `MakeNurb()`. + MakeNurb, + /// `Reparameterize(dom)`. + Reparam(Dom), + /// `ToggleSwapUVBit()`. + Toggle, + /// `RebuildSTEPFromNURBParameters()`. + Rebuild, + /// `DropPointFast(dom, op, p, NULL, tol, target, SM_SR_ALL)`. + Drop { + /// Domain. + dom: Dom, + /// `SmSolverOperationType` value (0 to 5). + op: u8, + /// Test point. + p: [f64; 3], + /// Distance tolerance. + tol: f64, + /// Optional target distance. + target: Option, + }, + /// `GlobalLineIntersect(dom, p, v, ivl, ray, tol)`. + Line { + /// Domain. + dom: Dom, + /// Line point. + p: [f64; 3], + /// Line vector. + v: [f64; 3], + /// Optional `SmExtent1d(a, b)`. + ivl: Option<[f64; 2]>, + /// Fire a ray. + ray: bool, + /// Distance tolerance. + tol: f64, + }, + /// `TrimPlaneLineToPlaneDomain(dom, a, b, tol)`. + TrimLine { + /// Domain. + dom: Dom, + /// Segment start. + a: [f64; 3], + /// Segment end. + b: [f64; 3], + /// 3D tolerance. + tol: f64, + }, + /// `CreateIsoParametricCurve(ctx, U or V, iso, 0, .., domain, &gap, want_uv)`. + Iso { + /// `false`: `SM_SP_U`, `true`: `SM_SP_V`. + v_dir: bool, + /// Iso parameter. + iso: f64, + /// Optional domain `SmExtent2d(umin, vmin, umax, vmax)`. + domain: Option<[f64; 4]>, + /// Also build the UV curve. + want_uv: bool, + }, + /// `DropCurve(ctx, dom, curve, ivl, tol, .., keep_all, NULL, creating)`. + DropCurve { + /// Domain. + dom: Dom, + /// The curve. + curve: CurveIn, + /// `SmExtent1d(a, b)`, or the curve's natural interval. + ivl: Option<[f64; 2]>, + /// Approximation tolerance. + tol: f64, + /// Keep all drop curves. + keep_all: bool, + /// Creating a UV trim curve. + creating: bool, + }, + /// `CoincidenceCheck(other, tol, .., whole, ..)`. + Coincidence { + /// Other surface. + other: SurfaceIn, + /// 3D tolerance. + tol: f64, + /// Whole surfaces. + whole: bool, + }, + /// `*A == *B`. + Eq(Box), + /// `Copy(ctx, p)`. + Copy, + /// `sm_IsGrazingIntersection(curve, t, CreateLineSegment(a, b), s)`. + Grazing { + /// The curve. + curve: CurveIn, + /// Curve parameter. + t: f64, + /// Line start and end. + line: [[f64; 3]; 2], + /// Line parameter. + s: f64, + }, + /// The inherited queries of a copy (`IsParallelToVector(v)`). + Inherited([f64; 3]), + /// `Reverse(U or V)` (`true`: `SM_SP_V`). + Reverse(bool), + /// `SwapUV()`. + Swap, +} + +fn bad(msg: &str) -> FfiError { + FfiError::InvalidArgument(msg.into()) +} + +fn finite(x: f64) -> Result { + if x.is_finite() && x.abs() <= MAX_COORD { + Ok(x) + } else { + Err(bad("non-finite or huge value")) + } +} + +/// Checks a clamped knot vector for `n1` control points of degree `p`. +fn check_knots(knots: &[f64], n1: usize, p: usize) -> Result<(), FfiError> { + if knots.len() != n1 + p + 1 { + return Err(bad("knot count")); + } + if knots.windows(2).any(|w| w.first() > w.last()) { + return Err(bad("knots decreasing")); + } + let (Some(&k0), Some(&km)) = (knots.first(), knots.last()) else { + return Err(bad("knot count")); + }; + if km <= k0 + || knots.iter().take(p + 1).any(|&k| k != k0) + || knots.iter().rev().take(p + 1).any(|&k| k != km) + { + return Err(bad("knots not clamped")); + } + let mut run = 0usize; + let mut last = f64::NAN; + for &k in knots.iter().filter(|&&k| k != k0 && k != km) { + run = if k == last { run + 1 } else { 1 }; + last = k; + if run > p { + return Err(bad("interior knot multiplicity")); + } + } + Ok(()) +} + +/// Checks the weights: all [`NOW`] or all in `(0, MAX_COORD]`. +fn check_weights<'a>(mut ws: impl Iterator) -> Result<(), FfiError> { + let Some(first) = ws.next() else { + return Err(bad("no control points")); + }; + let rational = first[3] != NOW; + let ok = |w: f64| if rational { w > 0.0 && w <= MAX_COORD } else { w == NOW }; + if !ok(first[3]) || ws.any(|c| !ok(c[3])) { + return Err(bad("weights")); + } + Ok(()) +} + +struct Enc(Vec); + +impl Enc { + fn num(&mut self, x: f64) -> Result<(), FfiError> { + self.0.push(finite(x)?); + Ok(()) + } + fn int(&mut self, x: usize) { + self.0.push(x as f64); + } + fn flag(&mut self, b: bool) { + self.0.push(if b { 1.0 } else { 0.0 }); + } + fn nums(&mut self, v: &[f64]) -> Result<(), FfiError> { + v.iter().try_for_each(|&x| self.num(x)) + } + fn cpt(&mut self, c: &[f64; 4]) -> Result<(), FfiError> { + self.nums(&c[..3])?; + // the weight was checked (NL_NOW or positive) + self.0.push(c[3]); + Ok(()) + } + + fn make(&mut self, m: &Make) -> Result<(), FfiError> { + match m { + Make::Bounded { + o, + x, + y, + scale, + domain, + } => { + self.int(0); + self.nums(o)?; + self.nums(x)?; + self.nums(y)?; + self.nums(scale)?; + self.nums(domain) + } + Make::Normal { o, n } => { + self.int(1); + self.nums(o)?; + self.nums(n) + } + Make::Canonical { o, x, y } => { + self.int(2); + self.nums(o)?; + self.nums(x)?; + self.nums(y) + } + } + } + + fn dom(&mut self, d: &Dom) -> Result<(), FfiError> { + match d { + Dom::Step => { + self.int(0); + self.nums(&[0.0; 4]) + } + Dom::Explicit(v) => { + self.int(1); + self.nums(v) + } + Dom::Natural => { + self.int(2); + self.nums(&[0.0; 4]) + } + } + } + + fn curve(&mut self, c: &CurveIn) -> Result<(), FfiError> { + match c { + CurveIn::Segment(a, b) => { + if a == b { + return Err(bad("degenerate segment")); + } + self.int(0); + self.nums(a)?; + self.nums(b) + } + CurveIn::BSpline(d) => { + let n1 = d.cpts.len(); + if !(2..=2 * MAX_INDEX + 1).contains(&n1) + || !(1..=MAX_DEGREE).contains(&d.p) + || d.p >= n1 + || (d.dim != 2 && d.dim != 3) + { + return Err(bad("B-spline curve size, degree or dimension")); + } + check_knots(&d.knots, n1, d.p)?; + check_weights(d.cpts.iter())?; + self.int(1); + self.int(d.dim as usize); + self.int(n1 - 1); + self.int(d.p); + self.int(d.knots.len() - 1); + for c in &d.cpts { + self.cpt(c)?; + } + self.nums(&d.knots) + } + } + } + + fn surface(&mut self, s: &SurfaceIn) -> Result<(), FfiError> { + match s { + SurfaceIn::Plane(m) => { + self.int(0); + self.make(m) + } + SurfaceIn::BSpline(d) => { + let n1 = d.net.len(); + let m1 = d.net.first().map_or(0, Vec::len); + if !(2..=MAX_INDEX + 1).contains(&n1) + || !(2..=MAX_INDEX + 1).contains(&m1) + || d.net.iter().any(|r| r.len() != m1) + || !(1..=MAX_DEGREE).contains(&d.p) + || !(1..=MAX_DEGREE).contains(&d.q) + || d.p >= n1 + || d.q >= m1 + { + return Err(bad("B-spline surface size or degree")); + } + check_knots(&d.u, n1, d.p)?; + check_knots(&d.v, m1, d.q)?; + check_weights(d.net.iter().flatten())?; + self.int(1); + self.int(n1 - 1); + self.int(m1 - 1); + self.int(d.p); + self.int(d.q); + self.int(d.u.len() - 1); + self.int(d.v.len() - 1); + for c in d.net.iter().flatten() { + self.cpt(c)?; + } + self.nums(&d.u)?; + self.nums(&d.v) + } + } + } + + fn op(&mut self, op: &Op) -> Result<(), FfiError> { + match op { + Op::State => self.int(1), + Op::Evaluate { uv, hu, hv, upper } => { + if *hu > 4 || *hv > 4 || (*upper && hu > hv) { + return Err(bad("derivative orders")); + } + self.int(2); + self.nums(uv)?; + self.int(*hu); + self.int(*hv); + self.flag(*upper); + } + Op::EvalPoint(uv) => { + self.int(3); + self.nums(uv)?; + } + Op::EvalFast(uv) => { + self.int(4); + self.nums(uv)?; + } + Op::Normal(uv) => { + self.int(5); + self.nums(uv)?; + } + Op::Project(p) => { + self.int(6); + self.nums(p)?; + } + Op::Queries(uv) => { + self.int(7); + self.nums(uv)?; + } + Op::KindOf(t) => { + if *t > 100_000 { + return Err(bad("type")); + } + self.int(8); + self.int(*t as usize); + } + Op::Adjust(d) => { + self.int(9); + self.dom(d)?; + } + Op::MakeNurb => self.int(10), + Op::Reparam(d) => { + self.int(11); + self.dom(d)?; + } + Op::Toggle => self.int(12), + Op::Rebuild => self.int(13), + Op::Drop { + dom, + op, + p, + tol, + target, + } => { + if *op > 5 { + return Err(bad("solver operation")); + } + self.int(14); + self.dom(dom)?; + self.int(usize::from(*op)); + self.nums(p)?; + self.num(*tol)?; + self.flag(target.is_some()); + self.num(target.unwrap_or(0.0))?; + } + Op::Line { + dom, + p, + v, + ivl, + ray, + tol, + } => { + self.int(15); + self.dom(dom)?; + self.nums(p)?; + self.nums(v)?; + self.flag(ivl.is_some()); + self.nums(&ivl.unwrap_or([0.0, 0.0]))?; + self.flag(*ray); + self.num(*tol)?; + } + Op::TrimLine { dom, a, b, tol } => { + self.int(16); + self.dom(dom)?; + self.nums(a)?; + self.nums(b)?; + self.num(*tol)?; + } + Op::Iso { + v_dir, + iso, + domain, + want_uv, + } => { + self.int(17); + self.flag(*v_dir); + self.num(*iso)?; + self.flag(domain.is_some()); + self.nums(&domain.unwrap_or([0.0; 4]))?; + self.flag(*want_uv); + } + Op::DropCurve { + dom, + curve, + ivl, + tol, + keep_all, + creating, + } => { + self.int(18); + self.dom(dom)?; + self.curve(curve)?; + self.flag(ivl.is_some()); + self.nums(&ivl.unwrap_or([0.0, 0.0]))?; + self.num(*tol)?; + self.flag(*keep_all); + self.flag(*creating); + } + Op::Coincidence { other, tol, whole } => { + self.int(19); + self.surface(other)?; + self.num(*tol)?; + self.flag(*whole); + } + Op::Eq(m) => { + self.int(20); + self.make(m)?; + } + Op::Copy => self.int(21), + Op::Grazing { curve, t, line, s } => { + if line[0] == line[1] { + return Err(bad("degenerate segment")); + } + self.int(22); + self.curve(curve)?; + self.num(*t)?; + self.nums(&line[0])?; + self.nums(&line[1])?; + self.num(*s)?; + } + Op::Inherited(v) => { + self.int(23); + self.nums(v)?; + } + Op::Reverse(v_dir) => { + self.int(24); + self.flag(*v_dir); + } + Op::Swap => self.int(25), + } + Ok(()) + } +} + +/// The flat program [`run`] hands the shim. +/// +/// # Errors +/// +/// [`FfiError::InvalidArgument`] for inputs [`run`] rejects. +pub fn encode(make: &Make, ops: &[Op]) -> Result, FfiError> { + if ops.len() > MAX_OPS { + return Err(bad("too many ops")); + } + let mut e = Enc(Vec::new()); + e.make(make)?; + e.int(ops.len()); + for op in ops { + e.op(op)?; + } + Ok(e.0) +} + +/// Builds plane A from `make`, runs `ops` on it and returns the record (see the module +/// docs). +/// +/// # Errors +/// +/// [`FfiError::InvalidArgument`] for rejected inputs; [`FfiError::Status`] for a shim +/// failure. +pub fn run(make: &Make, ops: &[Op]) -> Result, FfiError> { + let prog = encode(make, ops)?; + let n_in = i64::try_from(prog.len()).map_err(|_| bad("program too long"))?; + call_with_buffer(256, |buf: &mut [f64], len| { + // SAFETY: `prog` is valid for `n_in` reads; `buf` for `buf.len()` writes; `len` + // is a valid i64; nothing is retained. + unsafe { + sys::sc_surface_plane_p1_run( + prog.as_ptr(), + n_in, + buf.as_mut_ptr(), + buf.len() as i64, + &raw mut *len, + ) + } + }) +} diff --git a/crates/solidcore/src/curve/crv_on_surf.rs b/crates/solidcore/src/curve/crv_on_surf.rs index e76729a65b..e0b978fd5c 100644 --- a/crates/solidcore/src/curve/crv_on_surf.rs +++ b/crates/solidcore/src/curve/crv_on_surf.rs @@ -186,6 +186,11 @@ fn surface_read_from_db( "SmSurface virtuals of an SmCurveBoundedSurface", "surface.surface_p1", )), + // UNPORTED(surface.surface_p1): SmSurface dispatch for an SmPlane + SurfaceKind::Plane(_) => Err(SolidError::unported( + "SmSurface virtuals of an SmPlane", + "surface.surface_p1", + )), } } diff --git a/crates/solidcore/src/curve/iso_curve.rs b/crates/solidcore/src/curve/iso_curve.rs index ce4f81a481..e8c51bfa04 100644 --- a/crates/solidcore/src/curve/iso_curve.rs +++ b/crates/solidcore/src/curve/iso_curve.rs @@ -410,6 +410,11 @@ fn surface_read_from_db( "SmSurface virtuals of an SmCurveBoundedSurface", "surface.surface_p1", )), + // UNPORTED(surface.surface_p1): SmSurface dispatch for an SmPlane + SurfaceKind::Plane(_) => Err(SolidError::unported( + "SmSurface virtuals of an SmPlane", + "surface.surface_p1", + )), } } diff --git a/crates/solidcore/src/nurbs/b_spline_surface/p1.rs b/crates/solidcore/src/nurbs/b_spline_surface/p1.rs index d48a4e0b12..67a767b172 100644 --- a/crates/solidcore/src/nurbs/b_spline_surface/p1.rs +++ b/crates/solidcore/src/nurbs/b_spline_surface/p1.rs @@ -1034,23 +1034,20 @@ impl BSplineSurface { /// (or of every v column) lie on a line parallel to it (`IsParallelToVector`). /// `false` without NURB; `true` for a zero vector (see the module docs). /// + /// The `SmPlane` branch is + /// [`crate::surface::plane::Plane::is_parallel_to_vector`]. + /// /// # Errors /// - /// [`SolidError::Unported`] for an analytic plane (`SmPlane::GetPosition`). + /// None (the `Result` is kept for the derived surfaces). pub fn is_parallel_to_vector(&self, vector: Vec3) -> Result { let Ok(test_vec) = vector.unitize() else { // SER(sTestVec.Unitize()): SM_ERR_INVALID_INPUT returned as the boolean return Ok(true); }; - if self.is_kind_of(PLANE_TYPE)? { - // the SmPlane branch: |Z . v| < SM_EFF_ZERO * (1 + |origin|max) - // UNPORTED(surface.plane_p1): SmPlane::GetPosition - return Err(SolidError::Unported { - upstream: "SmPlane::GetPosition", - unit: "surface.plane_p1", - }); - } + // the SmPlane branch (|Z . v| < SM_EFF_ZERO * (1 + |origin|max)) is + // Plane::is_parallel_to_vector: a plane is never a plain BSplineSurface here let Some(sur) = self.nurb_ref() else { return Ok(false); // FS diff --git a/crates/solidcore/src/nurbs/b_spline_surface/p2.rs b/crates/solidcore/src/nurbs/b_spline_surface/p2.rs index 89936f2f83..e0e801e8f9 100644 --- a/crates/solidcore/src/nurbs/b_spline_surface/p2.rs +++ b/crates/solidcore/src/nurbs/b_spline_surface/p2.rs @@ -74,7 +74,7 @@ use crate::geom::axis2_placement::Axis2Placement; use crate::geom::extent1d::Extent1d; use crate::geom::extent2d::Extent2d; use crate::geom::geom_utility::p1::line_closest_point; -use crate::geom::vector2d::Point2; +use crate::geom::vector2d::{Point2, Vec2}; use crate::geom::vector3d::{Point3, Vec3}; use crate::kernel::Kernel; use crate::math::{EFF_ZERO, EFF_ZERO_SQRT}; @@ -88,6 +88,7 @@ use crate::nurbs::math::{NOW, NOZ}; use crate::nurbs::nurbs_srf::{is_nsrf_degenerate, split_srf}; use crate::nurbs::srf_basic::Direction; use crate::nurbs::srf_tool::p1::{extract_iso_crv, extract_patch}; +use crate::surface::plane::Plane; use super::p1::{ BSplineSurface, BSplineSurfaceForm, BoundingBoxRequest, CanonicalSurfaceData, SurfParamType, @@ -256,18 +257,25 @@ fn evaluate_1st_derivatives(_srf: &BSplineSurface, _uv: Point2) -> Result<(Point struct PlaneData { /// `EvaluateNormal` at the domain centre. normal: Vec3, - /// The points at the domain corners `(0, 0)`, `(0, 1)`, `(1, 0)`, `(1, 1)` + /// The points at the natural domain corners `(0, 0)`, `(0, 1)`, `(1, 0)`, `(1, 1)` /// (relative). corners: [Point3; 4], } -/// `new SmPlane(point, x_dir, y_dir, scale, domain)`, its normal and corners. -fn new_plane(_point: Point3, _x_dir: Vec3, _y_dir: Vec3, _domain: &Extent2d) -> Result { - // UNPORTED(surface.plane_p1): SmPlane::SmPlane - Err(SolidError::Unported { - upstream: "SmPlane::SmPlane", - unit: "surface.plane_p1", - }) +/// `new SmPlane(point, x_dir, y_dir, (1, 1), domain)`, its normal +/// (`EvaluateNormal`) and the points at the corners of its natural domain +/// (`EvaluatePoint` at `GetMin`, `(0, 1)`, `(1, 0)`, `GetMax`). +fn new_plane(point: Point3, x_dir: Vec3, y_dir: Vec3, domain: &Extent2d) -> PlaneData { + let plane = Plane::new(point, x_dir, y_dir, Vec2::new(1.0, 1.0), domain); + let normal = plane.evaluate_normal(); + let plane_domain = plane.natural_uv_domain(); + let corners = [ + plane.evaluate_point(plane_domain.min()), + plane.evaluate_point(plane_domain.evaluate(0.0, 1.0)), + plane.evaluate_point(plane_domain.evaluate(1.0, 0.0)), + plane.evaluate_point(plane_domain.max()), + ]; + PlaneData { normal, corners } } /// `SmSurface::CreateNaturalUVTrimCurves(domain, SM_SP_U, FALSE, ..)`: the 3D trimming @@ -873,7 +881,7 @@ impl BSplineSurface { let size = bbox.size(); let leng = size.length(); let tmp_domain = Extent2d::from_bounds(-leng, -leng, leng, leng); - let plane = new_plane(pnt, dv, du, &tmp_domain)?; + let plane = new_plane(pnt, dv, du, &tmp_domain); // Make sure both curves are on the plane before continuing. if !curve1.is_on_plane(pnt, plane.normal, tol, None)?.on_plane { diff --git a/crates/solidcore/src/surface.rs b/crates/solidcore/src/surface.rs index bcc26f7ea1..1a7e13eeeb 100644 --- a/crates/solidcore/src/surface.rs +++ b/crates/solidcore/src/surface.rs @@ -9,6 +9,7 @@ pub mod b_spline_volume; pub mod curve_bounded_surface; +pub mod plane; #[allow(clippy::module_inception)] pub mod surface; pub mod surface_cache; diff --git a/crates/solidcore/src/surface/plane.rs b/crates/solidcore/src/surface/plane.rs new file mode 100644 index 0000000000..6fb841f0b9 --- /dev/null +++ b/crates/solidcore/src/surface/plane.rs @@ -0,0 +1,10 @@ +//! Planes (`SmPlane`): an analytic plane `O + u * su * X + v * sv * Y` over a STEP +//! (analytic) domain, kept next to a bilinear B-spline (its NURB representation). +//! +//! Upstream: `source/SMLib/src/SmPlane.cpp`, `source/SMLib/inc/SmPlane.h`. +//! The file is split over the plan units `surface.plane_p1` and `_p2`; each lives in +//! its own submodule and adds methods to [`Plane`]. + +pub mod p1; + +pub use p1::{Coincidence, Plane, PlaneDropCurve, PlaneIsoCurve}; diff --git a/crates/solidcore/src/surface/plane/p1.rs b/crates/solidcore/src/surface/plane/p1.rs new file mode 100644 index 0000000000..9f429aca43 --- /dev/null +++ b/crates/solidcore/src/surface/plane/p1.rs @@ -0,0 +1,2241 @@ +//! `SmPlane`, part 1: the plane object ([`Plane`]: the analytic definition +//! `O + u * su * X + v * sv * Y` over a STEP domain next to its bilinear NURB), its +//! constructors, copies, evaluation, projection, point and line solvers, iso-curves, +//! curve drops, coincidence test, re-parameterisation, u/v swap and the analytic data +//! rebuilt from the NURB. +//! +//! Upstream: `source/SMLib/src/SmPlane.cpp`, `source/SMLib/inc/SmPlane.h`. +//! +//! | Rust | Upstream | +//! |-----------------------------------------------|---------------------------------------------------| +//! | [`Plane`] | `SmPlane` | +//! | [`Plane::new`] | `SmPlane(Origin, XAxis, YAxis, UVScale, UVDomain, cpContext)` | +//! | [`Plane::from_normal`] | `SmPlane(Origin, PlaneNormal, cpContext)` | +//! | [`Plane::create_canonical`] | `CreateCanonical` | +//! | `Clone`, [`Plane::copy`] | copy constructor, `Copy` (both overloads) | +//! | `Drop` (implicit) | `~SmPlane` | +//! | [`Plane::approx_eq`] | `operator==` | +//! | [`Plane::adjust_step_uv_domain`] | `AdjustSTEPUVDomain` | +//! | [`Plane::coincidence_check`], [`Coincidence`] | `CoincidenceCheck` | +//! | [`Plane::create_iso_parametric_curve`], [`PlaneIsoCurve`] | `CreateIsoParametricCurve` | +//! | [`Plane::drop_curve`], [`PlaneDropCurve`] | `DropCurve` | +//! | [`Plane::drop_point_fast`] | `DropPointFast` | +//! | [`Plane::evaluate_point`], [`Plane::evaluate_point_fast`] | `EvaluatePoint`, `EvaluatePointFast` | +//! | [`Plane::evaluate`], [`Plane::evaluate_simple`] | `Evaluate`, `EvaluateSimple` (inline) | +//! | [`Plane::evaluate_normal`] | `EvaluateNormal` | +//! | [`Plane::global_line_intersect`] | `GlobalLineIntersect` | +//! | [`Plane::trim_plane_line_to_plane_domain`] | `TrimPlaneLineToPlaneDomain` | +//! | [`is_grazing_intersection`] | `sm_IsGrazingIntersection` (static) | +//! | [`Plane::is_bounded`] | `IsBounded` | +//! | [`Plane::is_singularity`], [`Plane::is_singularity_with_poles`] | `IsSingularity` (both overloads) | +//! | [`Plane::is_planar`], [`Plane::is_on_seam`], [`Plane::is_closed`] | `IsPlanar`, `IsOnSeam`, `IsClosed` (inline) | +//! | [`Plane::make_nurb`] | `MakeNurb` | +//! | [`Plane::project_point_to_uv_domain`] | `ProjectPointToUVDomain` | +//! | [`Plane::reparameterize`] | `Reparameterize` | +//! | [`Plane::toggle_swap_uv_bit`] | `ToggleSwapUVBit` | +//! | [`Plane::rebuild_step_from_nurb_parameters`] | `RebuildSTEPFromNURBParameters` | +//! | [`Plane::step_uv_domain`], [`Plane::position`], [`Plane::uv_scale`] | `GetSTEPUVDomain`, `GetPosition`, `GetUVScale` | +//! | [`Plane::is_kind_of`], [`Plane::TYPE`], [`Plane::type_string`], [`Plane::class_string`] | `IsKindOf`, `GetType`, `GetTypeString`, `GetClassString` (`SM_COMMON`) | +//! | [`Plane::base`], [`Plane::base_with_nurb`], [`Plane::natural_uv_domain`] | the `SmBSplineSurface` part, `GetOrCreateGwNurbPointer`, `GetNaturalUVDomain` (inherited) | +//! | [`Plane::max_analytic_domain`], [`Plane::is_parallel_to_vector`], [`Plane::reverse`], [`Plane::swap_uv`] | `SmBSplineSurface::GetMaxAnalyticDomain`, `IsParallelToVector`, `Reverse`, `SwapUV` (inherited, re-dispatched) | +//! +//! Deviations: +//! - **Derived class.** `SmPlane` derives from `SmBSplineSurface`; a [`Plane`] holds +//! its B-spline part ([`Plane::base`]) next to the analytic data, and is the +//! [`SurfaceKind::Plane`] kind of [`Surface`]. Inherited methods whose upstream +//! bodies call `SmPlane` overrides through the virtual table (`MakeNurb`, +//! `ToggleSwapUVBit`, `RebuildSTEPFromNURBParameters`, `IsPlanar`) are +//! re-dispatched here. A missing NURB is made with [`Plane::make_nurb`] where +//! upstream calls `GetOrCreateGwNurbPointer`: `&mut self` methods make it in +//! place, read-only methods (upstream `const` methods that make it through a +//! `const_cast`) make it on a copy ([`Plane::base_with_nurb`]), so the plane keeps +//! none (so does the source of a copy). The observable differences are the NURB a +//! later [`Plane::toggle_swap_uv_bit`] leaves alone and `operator==`, which compares +//! the NURBs. +//! - **Arguments.** Out-params become return values; `SmContext` arguments and the +//! arguments upstream marks `NotUsed` (`DropPointFast`'s pointing vector and +//! solution request, `Evaluate`'s sides and zero-tangent flags, +//! `CreateIsoParametricCurve`'s tolerance, `DropCurve`'s fail record, the +//! singularity tolerances and pole data) are dropped. Solutions of +//! [`Plane::drop_point_fast`] name `this` through an optional caller handle. +//! `CoincidenceCheck`'s containing surface is always `this` and is not returned. +//! - **`Evaluate`** writes beyond its array upstream when `bOnlyUpperHalf` is given +//! with more `u` than `v` derivatives; the port returns `InvalidInput` there. +//! Entries upstream leaves untouched are zero. +//! - **`Reparameterize`** computes a new origin only in debug code: the release +//! build keeps the old origin while changing the scales and the domain, so the +//! analytic plane moves unless the new domain starts where the old one did. The +//! port keeps that (`plan/findings.md`). Its `Notify` calls only drop caches and +//! inform owners and are omitted, as for B-splines. +//! - **Co-ported callees.** `SmSurface::Evaluate1stDerivatives` / +//! `Evaluate2ndDerivatives` (unit `surface.surface_p1`) are one-line wrappers of the +//! virtual `Evaluate` and are ported here over [`Surface::evaluate`]; +//! `SmTol::MapTo2d(SmTol3d, SmVector2d, SmSurface)` (unit `geom.tol`, waiting on +//! those wrappers) is ported here for a plane (the only surface it is called with). +//! - **Unported callees.** `SmSurface::IsPlanar` / `EvaluateNormal` of a surface +//! that is not a plane (`surface.surface_p7`), `CreateNaturalUVTrimCurves` +//! (`surface.surface_p6`), `DropPoint` (`surface.surface_p5`), the general +//! `SmSurface::DropCurve` (`intersect.surface_drop_lib_p3`) and the general +//! `SmSurface::GlobalLineIntersect` (`surface.surface_p8`) return +//! [`SolidError::Unported`]. Statuses upstream ignores are propagated where +//! upstream would go on with uninitialised values. + +use std::borrow::Cow; + +use crate::curve::curve::p8::CurveIntersectOptions; +use crate::curve::curve::{Curve, CurveKind}; +use crate::curve::iso_curve::IsoCurve; +use crate::curve::line::{BoundedLineOptions, Line}; +use crate::error::{ignore_status, Result, SolidError}; +use crate::geom::axis2_placement::Axis2Placement; +use crate::geom::extent1d::Extent1d; +use crate::geom::extent2d::Extent2d; +use crate::geom::geom_utility::p1::{ + line_closest_point, line_point_distance, plane_point_distance, +}; +use crate::geom::geom_utility::p2::ContinuityType; +use crate::geom::global_solver::SolverOperation; +use crate::geom::solution_array::{ + ObjectKind, Solution, SolutionArray, SolutionObject, SolutionType, +}; +use crate::geom::tol::{are_same, scaled_zero, tol3d}; +use crate::geom::vector2d::{Point2, Vec2}; +use crate::geom::vector3d::sqrt; +use crate::geom::vector3d::{Point3, Vec3}; +use crate::kernel::Kernel; +use crate::math::{ + max2, min2, rad_to_deg, BIG_DOUBLE, EFF_ZERO, EFF_ZERO_DEG, EFF_ZERO_SQ, EFF_ZERO_SQRT, + INFINITE_PARAMETER, +}; +use crate::nurbs::b_spline_curve::{BSplineCurve, CanonicalData, KnotType}; +use crate::nurbs::b_spline_curve_n_lib::TrimMode; +use crate::nurbs::b_spline_surface::{ + BSplineSurface, BSplineSurfaceForm, CanonicalSurfaceData, SurfParamType, +}; +use crate::nurbs::b_spline_surface_n_lib::p2::EvaluateFlags; +use crate::nurbs::knots::Side; +use crate::surface::surface::p2::{Surface, SurfaceKind, PLANE_TYPE}; + +const OP_EVAL: &str = "surface::plane::p1::Plane::evaluate"; +const OP_DROP: &str = "surface::plane::p1::Plane::drop_point_fast"; +const OP_LINE: &str = "surface::plane::p1::Plane::global_line_intersect"; + +/// A plane (`SmPlane`): `P(u, v) = O + u * su * X + v * sv * Y` with the origin `O` +/// and unit axes `X`, `Y` of [`Plane::position`] and the scales `(su, sv)` of +/// [`Plane::uv_scale`], evaluated over the STEP domain [`Plane::step_uv_domain`], +/// next to the bilinear B-spline of that domain ([`Plane::base`]). +#[derive(Debug)] +pub struct Plane { + /// The `SmBSplineSurface` part (the NURB representation). + base: BSplineSurface, + /// `m_vPosition`: origin, unit X axis and unit Y axis. + position: Axis2Placement, + /// `m_vAnalUVDomain`: the analytic (STEP) domain. + anal_uv_domain: Extent2d, + /// `m_vUVScale`: the u and v scales. + uv_scale: Vec2, +} + +/// The result of [`Plane::coincidence_check`]. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Coincidence { + /// `rbAreCoincident`. + pub are_coincident: bool, + /// `rdMaxDistanceBetween`: the largest distance measured (`-1` when none was). + pub max_distance: f64, +} + +/// The result of [`Plane::create_iso_parametric_curve`]. +#[derive(Debug, Clone)] +pub struct PlaneIsoCurve { + /// `rpNewIsoCurve`: the 3D iso line. + pub curve: Line, + /// `pOptMaxGap3d`: always `0` (the line is exact). + pub max_gap_3d: f64, + /// `pOptUVIsoCurve`: the 2D UV line when asked for and built. + pub uv_iso_curve: Option, +} + +/// The result of [`Plane::drop_curve`]. +#[derive(Debug, Clone)] +pub struct PlaneDropCurve { + /// `rdMaxDropToSurf`: the largest distance between the curve and its drop. + pub max_drop_to_surf: f64, + /// `rdMaxApproxDev`: the deviation of the UV curves from the ideal drop. + pub max_approx_dev: f64, + /// `rUVCurves`: the UV curves (none, or one 2D line or B-spline). + pub uv_curves: Vec, +} + +/// The copy constructor ([`Plane::copy`]). +impl Clone for Plane { + fn clone(&self) -> Self { + self.copy() + } +} + +impl Plane { + /// `SmPlane_TYPE`. + pub const TYPE: i64 = PLANE_TYPE; + + // ---- construction ----------------------------------------------------------------- + + /// The bounded plane `origin + u * uv_scale.x * X + v * uv_scale.y * Y` over + /// `uv_domain` (`SmPlane(Origin, XAxis, YAxis, UVScale, UVDomain, cpContext)`): + /// the axes are set with `SmAxis2Placement::SetCanonical` (made unit and + /// perpendicular; its status is ignored). No NURB is made. + #[must_use] + pub fn new( + origin: Point3, + x_axis: Vec3, + y_axis: Vec3, + uv_scale: Vec2, + uv_domain: &Extent2d, + ) -> Self { + let mut position = Axis2Placement::IDENTITY; + // SE: the status is only logged + let _ = position.set_canonical(origin, x_axis, y_axis); + Self { + base: BSplineSurface::new(), + position, + anal_uv_domain: *uv_domain, + uv_scale, + } + } + + /// The infinite plane through `origin` with normal `normal` (`SmPlane(Origin, + /// PlaneNormal, cpContext)`): unit scales, the domain + /// `[-SM_INFINITE_PARAMETER, SM_INFINITE_PARAMETER]^2` and the axes of + /// `MakeUnitOrthoVectors` (undefined for a zero normal, as upstream). No NURB is + /// made. + #[must_use] + pub fn from_normal(origin: Point3, normal: Vec3) -> Self { + let (s_y, s_z) = match normal.make_unit_ortho_vectors(None) { + Ok([_, y, z]) => (y, z), + // SE: the outputs keep their default (undefined) values + Err(_) => (Vec3::UNDEF, Vec3::UNDEF), + }; + let mut position = Axis2Placement::IDENTITY; + let _ = position.set_canonical(origin, s_y, s_z); + + // Make the plane m_vAnalUVDomain essentially infinite + let anal_uv_domain = Extent2d::from_bounds( + -INFINITE_PARAMETER, + -INFINITE_PARAMETER, + INFINITE_PARAMETER, + INFINITE_PARAMETER, + ); + Self { + base: BSplineSurface::new(), + position, + anal_uv_domain, + uv_scale: Vec2::new(1.0, 1.0), + } + } + + /// The infinite plane of `origin` (its origin and axes, unit scales, domain + /// `[-SM_INFINITE_PARAMETER, SM_INFINITE_PARAMETER]^2`) with its NURB + /// (`CreateCanonical`). + /// + /// # Errors + /// + /// Those of [`Plane::make_nurb`]. + pub fn create_canonical(origin: &Axis2Placement) -> Result { + let uv_scale = Vec2::new(1.0, 1.0); + let uv_domain = Extent2d::from_bounds( + -INFINITE_PARAMETER, + -INFINITE_PARAMETER, + INFINITE_PARAMETER, + INFINITE_PARAMETER, + ); + let mut plane = Self::new( + origin.origin(), + origin.x_axis(), + origin.y_axis(), + uv_scale, + &uv_domain, + ); + plane.make_nurb()?; + Ok(plane) + } + + /// An exact copy (`Copy`, the copy constructor): the B-spline part is copied + /// with the NURB of [`Plane::base_with_nurb`] (upstream makes the source's missing + /// NURB first, through a `const_cast`; here the source keeps none). + #[must_use] + pub fn copy(&self) -> Self { + let mut src = self.member_copy(); + if src.base.gw_nurb().is_none() { + let _ = src.make_nurb(); + } + Self { + base: src.base.copy(), + ..src + } + } + + /// A copy of every member as is (no NURB is made). + fn member_copy(&self) -> Self { + Self { + base: self.base.copy(), + position: self.position, + anal_uv_domain: self.anal_uv_domain, + uv_scale: self.uv_scale, + } + } + + /// Upstream `operator==`: the B-spline parts are equal + /// ([`BSplineSurface::approx_eq`]) and the positions, domains and scales are + /// equal within upstream's tolerances. + #[must_use] + pub fn approx_eq(&self, other: &Self) -> bool { + // low work + if core::ptr::eq(self, other) { + return true; + } + + // first check the base + if !self.base.approx_eq(&other.base) { + return false; + } + + // check equivalence of these objects + self.position.approx_eq(&other.position) + && self.anal_uv_domain.are_same(&other.anal_uv_domain) + && self.uv_scale.approx_eq(other.uv_scale) + } + + // ---- accessors -------------------------------------------------------------------- + + /// The `SmBSplineSurface` part. + #[must_use] + pub const fn base(&self) -> &BSplineSurface { + &self.base + } + + /// The B-spline part with a NURB: the stored one, or one made on a copy when the + /// plane has none (`GetOrCreateGwNurbPointer` from a `const` method). + /// + /// # Errors + /// + /// Those of [`Plane::make_nurb`]. + pub fn base_with_nurb(&self) -> Result> { + if self.base.gw_nurb().is_some() { + return Ok(Cow::Borrowed(&self.base)); + } + let mut tmp = self.member_copy(); + tmp.make_nurb()?; + Ok(Cow::Owned(tmp.base)) + } + + /// The B-spline part for an inherited query: with a NURB when one can be made, + /// else the part without NURB (upstream's `NULL` NURB). + pub(crate) fn base_for_query(&self) -> Cow<'_, BSplineSurface> { + self.base_with_nurb().unwrap_or(Cow::Borrowed(&self.base)) + } + + /// Makes the NURB when missing (`GetOrCreateGwNurbPointer` of a non-`const` + /// method; a failure leaves the plane without NURB). + fn ensure_nurb(&mut self) { + if self.base.gw_nurb().is_none() { + let _ = self.make_nurb(); + } + } + + /// The position: origin and unit axes (`GetPosition`). + #[must_use] + pub const fn position(&self) -> &Axis2Placement { + &self.position + } + + /// The u and v scales (`GetUVScale`). + #[must_use] + pub const fn uv_scale(&self) -> Vec2 { + self.uv_scale + } + + /// The analytic (STEP) domain (`GetSTEPUVDomain`). + #[must_use] + pub const fn step_uv_domain(&self) -> Extent2d { + self.anal_uv_domain + } + + /// The natural (NURB) domain (`SmBSplineSurface::GetNaturalUVDomain`, inherited): + /// the knot range of the NURB, made on a copy when missing; `(0, 0, 0, 0)` when + /// none can be made. + #[must_use] + pub fn natural_uv_domain(&self) -> Extent2d { + self.base_for_query().natural_uv_domain() + } + + /// `SmPlane_TYPE` (`GetType`). + #[must_use] + pub const fn type_code(&self) -> i64 { + Self::TYPE + } + + /// `"SmPlane_TYPE"` (`GetTypeString`). + #[must_use] + pub const fn type_string(&self) -> &'static str { + "SmPlane_TYPE" + } + + /// `"SmPlane"` (`GetClassString`). + #[must_use] + pub const fn class_string(&self) -> &'static str { + "SmPlane" + } + + /// True for `SmPlane_TYPE` and the base types of `SmBSplineSurface` (`IsKindOf`). + /// + /// # Errors + /// + /// Those of [`BSplineSurface::is_kind_of`]. + pub fn is_kind_of(&self, t: i64) -> Result { + if t == Self::TYPE { + return Ok(true); + } + self.base.is_kind_of(t) + } + + // ---- simple queries --------------------------------------------------------------- + + /// Whether the analytic domain is bounded (`IsBounded`). + #[must_use] + pub fn is_bounded(&self) -> bool { + self.anal_uv_domain.is_bounded() + } + + /// `IsPlanar`: always planar; the plane point (the origin), the normal (the Z + /// axis) and the deviation `0`. + #[must_use] + pub fn is_planar(&self) -> (Point3, Vec3, f64) { + (self.position.origin(), self.position.z_axis(), 0.0) + } + + /// `IsOnSeam`: a plane has no seam (`false`, seam direction + /// [`SurfParamType::Neither`], no cross-seam points). + #[must_use] + pub const fn is_on_seam(&self) -> (bool, SurfParamType) { + (false, SurfParamType::Neither) + } + + /// `IsClosed`: never closed, continuity [`ContinuityType::Discontinuous`]. + #[must_use] + pub const fn is_closed(&self) -> (bool, ContinuityType) { + (false, ContinuityType::Discontinuous) + } + + /// `IsSingularity` (point test): a plane has none (`false`, + /// [`SurfParamType::Neither`]). + #[must_use] + pub const fn is_singularity(&self) -> (bool, SurfParamType) { + (false, SurfParamType::Neither) + } + + /// `IsSingularity` (with known singular sides and pole points): a plane has none + /// (`false`, [`SurfParamType::Neither`]). + #[must_use] + pub const fn is_singularity_with_poles(&self) -> (bool, SurfParamType) { + (false, SurfParamType::Neither) + } + + /// `SmBSplineSurface::GetMaxAnalyticDomain` (inherited): planar, so the natural + /// domain expanded relatively by 100. + #[must_use] + pub fn max_analytic_domain(&self) -> Extent2d { + let mut dom = self.natural_uv_domain(); + dom.expand_relative(100.0); + dom + } + + /// `SmBSplineSurface::IsParallelToVector` (inherited), its `SmPlane` branch: the + /// normal is perpendicular to `vector` within `SM_EFF_ZERO * (1 + |O|max)`; + /// `true` for a zero vector (upstream returns the failed `Unitize` status). + #[must_use] + pub fn is_parallel_to_vector(&self, vector: Vec3) -> bool { + let Ok(test_vec) = vector.unitize() else { + return true; + }; + let z_axis = self.position.z_axis(); + let tol1 = EFF_ZERO * (1.0 + self.position.origin().max_dimension()); + z_axis.dot(test_vec).abs() < tol1 + } + + // ---- evaluation ------------------------------------------------------------------- + + /// The point at `uv`, clamped to the analytic domain unless out-of-bounds + /// evaluation is enabled (`EvaluatePoint`). + #[must_use] + pub fn evaluate_point(&self, uv: Point2) -> Point3 { + let mut s_uv = uv; + + // clamp UVPoint to UVDomain + if !self.base.is_out_of_bounds_enabled() && !self.anal_uv_domain.contains_point(s_uv, 0.0) { + s_uv = self.anal_uv_domain.clamp_point(s_uv); + } + + // evaluate + self.position.origin() + + s_uv.x * self.uv_scale.x * self.position.x_axis() + + s_uv.y * self.uv_scale.y * self.position.y_axis() + } + + /// The point at `step_uv`, not clamped (`EvaluatePointFast`). + #[must_use] + pub fn evaluate_point_fast(&self, step_uv: Point2) -> Point3 { + self.position.origin() + + step_uv.x * self.position.x_axis() * self.uv_scale.x + + step_uv.y * self.position.y_axis() * self.uv_scale.y + } + + /// The point and partial derivatives at `uv` (`Evaluate`): `D[i][j]` is the + /// derivative `i` times in `u` and `j` times in `v`; only the point and the first + /// derivatives are nonzero. `uv` is clamped as in [`Plane::evaluate_point`]. + /// + /// # Errors + /// + /// `InvalidInput` for `only_upper_half` with more `u` than `v` derivatives + /// (upstream writes outside its array). + pub fn evaluate( + &self, + uv: Point2, + highest_u_deriv: usize, + highest_v_deriv: usize, + only_upper_half: bool, + ) -> Result>> { + if only_upper_half && highest_u_deriv > highest_v_deriv { + return Err(SolidError::invalid_input( + OP_EVAL, + "only upper half with more u than v derivatives", + )); + } + + // local + let mut s_uv = uv; + + // when appropriate - clamp uncontained points + if !self.base.is_out_of_bounds_enabled() && !self.anal_uv_domain.contains_point(s_uv, 0.0) { + s_uv = self.anal_uv_domain.clamp_point(s_uv); + } + + // init output - every entry zero + let mut d = vec![vec![Vec3::ZERO; highest_v_deriv + 1]; highest_u_deriv + 1]; + + // position + if let Some(p) = d.get_mut(0).and_then(|r| r.get_mut(0)) { + *p = self.position.origin() + + s_uv.x * self.position.x_axis() * self.uv_scale.x + + s_uv.y * self.position.y_axis() * self.uv_scale.y; + } + + // 1st derivs + if highest_v_deriv > 0 { + if let Some(p) = d.get_mut(0).and_then(|r| r.get_mut(1)) { + *p = self.position.y_axis() * self.uv_scale.y; + } + } + if highest_u_deriv > 0 { + if let Some(p) = d.get_mut(1).and_then(|r| r.get_mut(0)) { + *p = self.position.x_axis() * self.uv_scale.x; + } + } + + // higher order derivatives already set to zero - no more work to do. + Ok(d) + } + + /// [`Plane::evaluate`] (`EvaluateSimple`). + /// + /// # Errors + /// + /// Those of [`Plane::evaluate`]. + pub fn evaluate_simple( + &self, + uv: Point2, + highest_u_deriv: usize, + highest_v_deriv: usize, + only_upper_half: bool, + ) -> Result>> { + self.evaluate(uv, highest_u_deriv, highest_v_deriv, only_upper_half) + } + + /// The unit normal, the Z axis (`EvaluateNormal`). + #[must_use] + pub fn evaluate_normal(&self) -> Vec3 { + self.position.z_axis() + } + + /// `SmSurface::Evaluate1stDerivatives(uv, TRUE, TRUE, ..)` of the plane: the point, + /// `S_u` and `S_v` of [`Plane::evaluate`] (upper half, non-zero tangents). + fn evaluate_1st_derivatives(&self, uv: Point2) -> Result<(Point3, Vec3, Vec3)> { + let m = self.evaluate(uv, 1, 1, true)?; + let at = |i: usize, j: usize| { + m.get(i) + .and_then(|r| r.get(j)) + .copied() + .unwrap_or(Vec3::ZERO) + }; + Ok((at(0, 0), at(1, 0), at(0, 1))) + } + + /// `SmTol::MapTo2d(SmTol3d(tol_3d), uv, *this)`: the 3D tolerance mapped to the + /// UV space of the plane in the direction of its larger first derivative. + fn map_to_2d(&self, tol_3d: f64, uv: Point2) -> Result { + // evaluate SurfacePt = rSurface(rUVTrimCurve(dParam)) + let (_, du, dv) = self.evaluate_1st_derivatives(uv)?; + + // pick the max 1st deriv direction + let uv_dir = if du.length_squared() > dv.length_squared() { + Vec2::new(1.0, 0.0) + } else { + Vec2::new(0.0, 1.0) + }; + + // pass the call along for Max 1st deriv (yields Min Tol2d value) + let (_, du, dv) = self.evaluate_1st_derivatives(uv)?; + + // locals + let uv_domain = self.natural_uv_domain(); + let scaled_zero = scaled_zero(); + let du_size = du.length(); + let dv_size = dv.length(); + + // Scale dTol3d to dTolUV in the U and V directions + let scaled_u = if du_size < scaled_zero { + uv_domain.u_interval().length() / 100.0 + } else { + tol_3d / du_size + }; + let scaled_v = if dv_size < scaled_zero { + uv_domain.v_interval().length() / 100.0 + } else { + tol_3d / dv_size + }; + + // get directional Tol2d value when [dDirU dDirV] is not the zero vector + let size = sqrt(uv_dir.x * uv_dir.x + uv_dir.y * uv_dir.y); + Ok(if size < scaled_zero { + min2(scaled_u, scaled_v) + } else { + uv_dir.x.abs() / size * scaled_u + uv_dir.y.abs() / size * scaled_v + }) + } + + /// The UV coordinates of `point` projected onto the infinite plane + /// (`ProjectPointToUVDomain`). + #[must_use] + pub fn project_point_to_uv_domain(&self, point: Point3) -> Point2 { + let vec = point - self.position.origin(); + let u_projection = self.position.x_axis().dot(vec); + let v_projection = self.position.y_axis().dot(vec); + Point2::new( + u_projection / self.uv_scale.x, + v_projection / self.uv_scale.y, + ) + } + + // ---- NURB ------------------------------------------------------------------------- + + /// Replaces the NURB by the bilinear B-spline through the four corners of the + /// analytic domain, knots `[umin, umin, umax, umax] x [vmin, vmin, vmax, vmax]` + /// (`MakeNurb`). + /// + /// # Errors + /// + /// Those of [`BSplineSurface::create_canonical`] (the NURB is unchanged). + pub fn make_nurb(&mut self) -> Result<()> { + // evaluate and save the 4 3d corner positions of the m_vAnalUVDomain + let d = self.anal_uv_domain; + let ctrl_pts = [ + self.evaluate_point_fast(d.evaluate(0.0, 0.0)), + self.evaluate_point_fast(d.evaluate(0.0, 1.0)), + self.evaluate_point_fast(d.evaluate(1.0, 0.0)), + self.evaluate_point_fast(d.evaluate(1.0, 1.0)), + ]; + + // set knot vectors to the corners of the m_vAnalUVDomain extent + let u_knots = [d.min().x, d.max().x]; + let v_knots = [d.min().y, d.max().y]; + + // set endPoint knot multiplicities + let mults = [2usize, 2]; + + // create temporary planar Bspline surface + let tmp = BSplineSurface::create_canonical(&CanonicalSurfaceData { + u_degree: 1, + v_degree: 1, + control_points: &ctrl_pts, + form: BSplineSurfaceForm::PlaneSurf, + u_multiplicities: &mults, + v_multiplicities: &mults, + u_knots: &u_knots, + v_knots: &v_knots, + knot_type: KnotType::Unspecified, + weights: None, + uv_domain: None, + })?; + + // Swap nurbs - old nurb is deleted with the temporary + self.base.nurb = tmp.nurb; + Ok(()) + } + + /// Sets the analytic domain to `new_step_uv_domain` and remakes the NURB, unless + /// the two domains contain each other within `SM_EFF_ZERO` (`AdjustSTEPUVDomain`). + /// + /// # Errors + /// + /// Those of [`Plane::make_nurb`]. + pub fn adjust_step_uv_domain(&mut self, new_step_uv_domain: &Extent2d) -> Result<()> { + // no work - new domain is equal to current domain + if new_step_uv_domain.is_contained_by(&self.anal_uv_domain, EFF_ZERO) + && self + .anal_uv_domain + .is_contained_by(new_step_uv_domain, EFF_ZERO) + { + return Ok(()); + } + + // save the new UVDomain + self.anal_uv_domain = *new_step_uv_domain; + + // replace the m_pNurb pointer with a new Planar Nurb with the new Extent + self.make_nurb() + } + + /// Maps the domain onto `trim_domain` (`Reparameterize`): the NURB is + /// re-parameterised without changing its shape; the analytic domain becomes + /// `trim_domain` and the scales `su * |old u| / |new u|`, `sv * |old v| / |new + /// v|`; the origin is kept (see the module docs). + /// + /// # Errors + /// + /// Those of [`BSplineSurface::reparameterize`] (`SM_ERR_NULL_POINTER` when no + /// NURB can be made). + pub fn reparameterize(&mut self, trim_domain: &Extent2d) -> Result<()> { + // Get new Analytic parameters + let scale_x = (self.uv_scale.x * self.anal_uv_domain.x_length()) / trim_domain.x_length(); + let scale_y = (self.uv_scale.y * self.anal_uv_domain.y_length()) / trim_domain.y_length(); + // (sPointMax, sPointMin and sOriginMax are only used by debug code) + + // set NURB domain parameterization - no change in shape + self.ensure_nurb(); + self.base.reparameterize(trim_domain)?; + + // Set Analytic domain parameterization - no change in shape + self.anal_uv_domain = *trim_domain; + self.uv_scale = Vec2::new(scale_x, scale_y); + Ok(()) + } + + /// Transposes the STEP definition so that `Plane(u, v) = SwapPlane(v, u)`: swaps + /// the axes, the domain directions and the scales (`ToggleSwapUVBit`). The NURB + /// is not changed. + pub fn toggle_swap_uv_bit(&mut self) { + // m_vPosition swaps XAxis with YAxis + let origin = self.position.origin(); + let x_axis = self.position.x_axis(); + let y_axis = self.position.y_axis(); + let _ = self.position.set_canonical(origin, y_axis, x_axis); + + // transpose the m_vAnalUVDomain + self.anal_uv_domain.transpose(); + + // Swap the scale factors + self.uv_scale = Vec2::new(self.uv_scale.y, self.uv_scale.x); + } + + /// Rebuilds the analytic data from the NURB (`RebuildSTEPFromNURBParameters`): the + /// domain becomes the natural domain, the scales and axes come from three + /// corners of the NURB, and the origin is moved so that the domain minimum + /// evaluates to the first corner (using the old axes). + /// + /// # Errors + /// + /// Those of the B-spline evaluation ([`BSplineSurface::evaluate_point`]). + pub fn rebuild_step_from_nurb_parameters(&mut self) -> Result<()> { + // Make our analytic data match the Nurbs shape. + self.ensure_nurb(); + let nurb_domain = self.base.natural_uv_domain(); + + // Get three corner 3d points, to get position and length scales. + let pt00 = self.base.evaluate_point(nurb_domain.evaluate(0.0, 0.0))?; + let pt01 = self.base.evaluate_point(nurb_domain.evaluate(0.0, 1.0))?; + let pt10 = self.base.evaluate_point(nurb_domain.evaluate(1.0, 0.0))?; + + // Set our scale first: 3d length divided by domain length. + let mut u_vec = pt10 - pt00; + let len_3d = u_vec.length(); + self.uv_scale.x = len_3d / nurb_domain.x_length(); + u_vec /= len_3d; // Unitize, for later. + + // V-scale: + let mut v_vec = pt01 - pt00; + let len_3d = v_vec.length(); + self.uv_scale.y = len_3d / nurb_domain.y_length(); + v_vec /= len_3d; // Unitize, for later. + + // The origin is where (0,0) would evaluate to. + let start_vec = nurb_domain.min().x * self.uv_scale.x * self.position.x_axis() + + nurb_domain.min().y * self.uv_scale.y * self.position.y_axis(); + + // The new origin would be the start point minus that vector. + let _ = self.position.set_canonical(pt00 - start_vec, u_vec, v_vec); + + // Finally update the domain. + self.anal_uv_domain = nurb_domain; + Ok(()) + } + + /// `SmBSplineSurface::Reverse` (inherited): reverses the NURB in `param`'s + /// direction, then rebuilds the analytic data from it. + /// + /// # Errors + /// + /// Those of [`BSplineSurface::reverse`] and + /// [`Plane::rebuild_step_from_nurb_parameters`]. + pub fn reverse(&mut self, param: SurfParamType) -> Result<()> { + self.ensure_nurb(); + self.base.reverse(param)?; + + // give analytics a chance to update their nested STEP data + self.rebuild_step_from_nurb_parameters() + } + + /// `SmBSplineSurface::SwapUV` (inherited): records the swap + /// ([`Plane::toggle_swap_uv_bit`]), transposes the NURB, then rebuilds the + /// analytic data from it. + /// + /// # Errors + /// + /// Those of [`BSplineSurface::canonical`], [`BSplineSurface::set_canonical`] and + /// [`Plane::rebuild_step_from_nurb_parameters`]. + pub fn swap_uv(&mut self) -> Result<()> { + // get current surface description + self.ensure_nurb(); + let c = self.base.canonical()?; + + // let analytic surfaces remember that they have been swapped + self.toggle_swap_uv_bit(); + + // Transpose Weights and control points arrays + let num_v_cpts = self.base.number_control_points(SurfParamType::V); + let mut cpts = c.control_points; + let mut weights = c.weights; + transpose(&mut cpts, num_v_cpts); + transpose(&mut weights, num_v_cpts); + + // Transpose Surface definition + self.base.set_canonical(&CanonicalSurfaceData { + u_degree: c.v_degree, + v_degree: c.u_degree, + control_points: &cpts, + form: c.form, + u_multiplicities: &c.v_multiplicities, + v_multiplicities: &c.u_multiplicities, + u_knots: &c.v_knots, + v_knots: &c.u_knots, + knot_type: c.knot_type, + weights: Some(&weights), + uv_domain: None, + })?; + self.rebuild_step_from_nurb_parameters() + } + + // ---- solvers ---------------------------------------------------------------------- + + /// The point of the plane closest to `test_point` within `uv_domain` + /// (`DropPointFast`): the projection clamped to the domain, as a single-value + /// solution `(u, v)` with the distance as value, naming `this`. No solution when + /// normalising and the projection is outside the domain (by more than the 3D + /// tolerance mapped to UV), when intersecting farther than + /// `distance_tolerance`, or when minimising or normalising farther than + /// `target_distance`. + /// + /// # Errors + /// + /// `SM_ERR` for another operation. + pub fn drop_point_fast( + &self, + uv_domain: &Extent2d, + operation: SolverOperation, + test_point: Point3, + distance_tolerance: f64, + target_distance: Option, + this: Option, + ) -> Result> { + // check input + if operation != SolverOperation::Minimize + && operation != SolverOperation::Normalize + && operation != SolverOperation::Intersect + { + return Err(SolidError::sm_err(OP_DROP)); + } + + // init output + let mut solutions = SolutionArray::new(); + + // Project targetPoint to plane + let mut uv_found = self.project_point_to_uv_domain(test_point); + + // when NORMALIZING - only use project solutions within the plane domain + if operation == SolverOperation::Normalize { + let tol_uv = self.map_to_2d(tol3d(distance_tolerance), uv_found)?; + if !uv_domain.contains_point(uv_found, tol_uv) { + return Ok(solutions); // No answer found + } + } + + // clamp projectPoint to planeDomain + uv_found = uv_domain.clamp_point(uv_found); + + // get 3dProjectPoint/TargetPoint gap + let pnt = self.evaluate_point_fast(uv_found); + let dist = pnt.distance(test_point); + + // when INTERSECTING skip solutions > DistanceTolerance + if operation == SolverOperation::Intersect && dist > distance_tolerance { + return Ok(solutions); // No answer found + } + + // when MINIMIZING or NORMALIZING skip solutions > TargetDistance + if let Some(target) = target_distance { + if (operation == SolverOperation::Minimize || operation == SolverOperation::Normalize) + && dist > target + { + return Ok(solutions); // No answer found + } + } + + let mut sol = Solution::new(); + sol.solution_type = SolutionType::SingleValue; + sol.num_objects = 1; + sol.objects[0] = this; + sol.nodes[0] = None; + sol.num_variables = 2; + sol.start.solution_value = dist; + sol.start.parameters[0] = uv_found.x; + sol.start.parameters[1] = uv_found.y; + solutions.add(&sol); + Ok(solutions) + } + + /// Intersections of the line `line_point + t * line_vector` with the plane over + /// `uv_domain` (`GlobalLineIntersect`): the line is infinite, a segment over + /// `line_interval`, or a ray from `t = 0` (`fire_ray`). A line not parallel to + /// the plane gives at most one single-value solution `(t, u, v)` (Cramer's rule, + /// `uv` clamped to the domain, within `distance_tolerance`); a line in the plane + /// gives the range of its part over the domain. Solutions name no objects. + /// + /// # Errors + /// + /// `InvalidInput` for a zero line vector; `SM_ERR` for a vanishing determinant; + /// [`SolidError::Unported`] when a line in the plane meets the domain in a single + /// line parameter (upstream then runs the general `SmSurface::GlobalLineIntersect`, + /// unit `surface.surface_p8`). + pub fn global_line_intersect( + &self, + uv_domain: &Extent2d, + line_point: Point3, + line_vector: Vec3, + line_interval: Option<&Extent1d>, + fire_ray: bool, + distance_tolerance: f64, + ) -> Result> { + if line_vector.length_squared() < EFF_ZERO_SQ { + return Err(SolidError::invalid_input(OP_LINE, "zero line vector")); + } + + // init output + let mut solutions = SolutionArray::new(); + + // locals + let plane_normal = self.evaluate_normal(); + let angle_tol = 0.0001; // 1/10000 of a degree + + // check for plane/curve coincidence + if plane_normal.is_perpendicular_to(line_vector, angle_tol) { + // Line and plane are nearly parallel - have either coincidence or miss. + // get interval to trim - given, infinite, or semi-infinite (for ray firing) + let mut ivl = if let Some(i) = line_interval { + *i + } else { + // Drop plane corners to line, to get param range of possible intersection. + let mut ivl = Extent1d::new(); + let lo = uv_domain.min(); + let hi = uv_domain.max(); + for uv in [ + lo, + Point2::new(lo.x, hi.y), + Point2::new(hi.x, lo.y), + Point2::new(hi.x, hi.y), + ] { + let pt = self.evaluate_point_fast(uv); + let line_param = line_closest_point(line_point, line_vector, pt); + ivl.add_value(line_param); + } + ivl.expand_relative(1.2); + ivl + }; + if fire_ray { + let _ = ivl.set_min_max(0.0, max2(ivl.max(), 0.0)); + } + + // get untrimmed interval endPoints + let mut plane_start_pt = line_point + ivl.min() * line_vector; + let mut plane_end_pt = line_point + ivl.max() * line_vector; + + // project untrimmed interval endPoints to plane UV params + let uv_start = self.project_point_to_uv_domain(plane_start_pt); + let uv_end = self.project_point_to_uv_domain(plane_end_pt); + + // build UVLine vector + let uv_vec = uv_end - uv_start; + + // find interval for UVLine that maps to plane domain + let Some(trim_ivl) = + uv_domain.intersect_with_infinite_line(uv_start, uv_vec, None, None) + else { + return Ok(solutions); + }; + + // handle round off - max UVLine interval is 0.0 to 1.0 + let d_min = max2(trim_ivl.min(), 0.0); + let d_max = min2(trim_ivl.max(), 1.0); + + if d_min > d_max + EFF_ZERO { + return Ok(solutions); // no trimmed portion in area of interest + } + + // get UVLine 2D trimmed endPoints + let trim_start = uv_start + d_min * uv_vec; + let trim_end = uv_start + d_max * uv_vec; + + // get associated 3D trimmed endPoints on Plane + plane_start_pt = self.evaluate_point_fast(trim_start); + plane_end_pt = self.evaluate_point_fast(trim_end); + + // get closest point on Line to trimmed plane start point + let t_start = line_closest_point(line_point, line_vector, plane_start_pt); + let test_start = line_point + t_start * line_vector; + let start_dist = test_start.distance(plane_start_pt); + + // quit when plane points are not close to line points + if start_dist > distance_tolerance { + return Ok(solutions); + } + + // get closest point on Line to trimmed plane end point + let t_end = line_closest_point(line_point, line_vector, plane_end_pt); + let test_end = line_point + t_end * line_vector; + let end_dist = test_end.distance(plane_end_pt); + + // quit when plane points are not close to line points + if end_dist > distance_tolerance { + return Ok(solutions); + } + + // when line parameters are the same + if are_same(t_start, t_end) { + // try global surface/curve solver + return surface_global_line_intersect(); + } + + // test that 3D Points project to UVDomain + let uv_start = self.project_point_to_uv_domain(plane_start_pt); + let uv_end = self.project_point_to_uv_domain(plane_end_pt); + + // build a coincident solution + let mut sol = Solution::new(); + sol.num_variables = 3; + sol.num_objects = 0; + sol.solution_type = SolutionType::RangeOfValues; + sol.start.solution_value = start_dist; + sol.start.parameters[0] = ivl.clamp_value(t_start); + sol.start.parameters[1] = uv_start.x; + sol.start.parameters[2] = uv_start.y; + + sol.end.solution_value = end_dist; + sol.end.parameters[0] = ivl.clamp_value(t_end); + sol.end.parameters[1] = uv_end.x; + sol.end.parameters[2] = uv_end.y; + + // set the output + solutions.add(&sol); + } else { + // Single intersection + // Set the curve domain. + let mut curve_domain = Extent1d::from_min_max(-1.0e10, 1.0e10); + if let Some(i) = line_interval { + curve_domain = *i; + } + if fire_ray { + let _ = curve_domain.set_min_max(0.0, BIG_DOUBLE); + } + + // u*Pu + v*Pv - t*Lt = (L0 - P0), solved by Cramer's rule. + let pu = self.position.x_axis() * self.uv_scale.x; + let pv = self.position.y_axis() * self.uv_scale.y; + let lt = -line_vector; + let diff = line_point - self.position.origin(); + + let det = pu.cross(pv).dot(lt); + if det.abs() < EFF_ZERO { + // should never happen, we're in the non-parallel case here. + return Err(SolidError::sm_err(OP_LINE)); + } + + // Cramer's rule: + let numer_t = pu.cross(pv).dot(diff); // triple product + let t_param = numer_t / det; + + // Check curve param vs. domain. + if !curve_domain.contains_value(t_param, 0.0) { + return Ok(solutions); // but no solution. + } + + let numer_u = diff.cross(pv).dot(lt); + let numer_v = pu.cross(diff).dot(lt); + let mut uv = Point2::new(numer_u / det, numer_v / det); + + // Eval curve and plane, and check whether they're within tol. + let line_pnt = line_point + t_param * line_vector; + + uv = uv_domain.clamp_point(uv); + let srf_pnt = self.evaluate_point_fast(uv); + let dist = srf_pnt.distance(line_pnt); + if dist > distance_tolerance { + return Ok(solutions); // but no solution. + } + + // Good to go, set up solution and get out. + let mut sol = Solution::new(); + sol.num_variables = 3; + sol.num_objects = 0; + sol.solution_type = SolutionType::SingleValue; + sol.start.solution_value = dist; + sol.start.parameters[0] = t_param; + sol.start.parameters[1] = uv.x; + sol.start.parameters[2] = uv.y; + solutions.add(&sol); + } + + Ok(solutions) + } + + /// The part of the segment `start_pt`-`end_pt` (projected onto the plane) over + /// `uv_domain` enlarged by `tol_3d` (mapped to UV with the larger scale) + /// (`TrimPlaneLineToPlaneDomain`): its trimmed end points, or `None` when the + /// segment misses the domain. An end of the segment touching the opposite end of + /// the domain interval within `SM_EFF_ZERO` gives that single point. + #[must_use] + pub fn trim_plane_line_to_plane_domain( + &self, + uv_domain: &Extent2d, + start_pt: Point3, + end_pt: Point3, + tol_3d: f64, + ) -> Option<(Point3, Point3)> { + let this_ivl = Extent1d::from_min_max(0.0, 1.0); + let uv_start = self.project_point_to_uv_domain(start_pt); + let uv_end = self.project_point_to_uv_domain(end_pt); + let uv_vec = uv_end - uv_start; + + // Find thisPlane and otherPlane line/domain intersection interval + let tol_uv = tol_3d / self.uv_scale.max_dimension(); + let plane_ivl = + uv_domain.intersect_with_infinite_line(uv_start, uv_vec, Some(tol_uv), None)?; + + // find the intersection between intersection result and input segment + let ivl = if (this_ivl.max() - plane_ivl.min()).abs() < EFF_ZERO { + // 1. degenerate overlap on ThisIvl max end + Extent1d::from_value(this_ivl.max()) + } else if (this_ivl.min() - plane_ivl.max()).abs() < EFF_ZERO { + // 2. degenerate overlap on ThisIvl min end + Extent1d::from_value(this_ivl.min()) + } else { + // 3. intersection of the two intervals (4. none: no intersection) + this_ivl.intersect(&plane_ivl).ok()? + }; + + // set outputs + let start = (1.0 - ivl.min()) * start_pt + ivl.min() * end_pt; + let end = (1.0 - ivl.max()) * start_pt + ivl.max() * end_pt; + Some((start, end)) + } + + // ---- curves ----------------------------------------------------------------------- + + /// The iso line of the plane at `iso_parameter` in `surf_param`'s direction + /// (constant `u` for [`SurfParamType::U`], else constant `v`) over the natural + /// domain or `domain` (`CreateIsoParametricCurve`): a 3D [`Line`] parameterised by + /// the other parameter. With `uv_iso_curve` the UV line of `SmIsoCurve` + /// (`CreateUVIsoLine`, built only for constant `u`; its status is ignored) is + /// returned too. + /// + /// # Errors + /// + /// Those of [`Line::create_line_segment`] (a degenerate line) and + /// [`Line::edit_parameterization`]. + pub fn create_iso_parametric_curve( + &self, + surf_param: SurfParamType, + iso_parameter: f64, + domain: Option<&Extent2d>, + uv_iso_curve: bool, + ) -> Result { + // get natural or optional domain min/max points + let uv_domain = self.natural_uv_domain(); + let mut p_min = uv_domain.min(); + let mut p_max = uv_domain.max(); + if let Some(d) = domain { + p_min = d.min(); + p_max = d.max(); + } + + // when asked - build associated 2d UVTrimCurve line (different parameterization) + let uv_curve = if uv_iso_curve { + // define the isoParameter Curve as an object + let base = self.base_for_query().into_owned(); + let iso = IsoCurve::new(base, surf_param, iso_parameter, true, true); + // build OptUVIsoCurve (status ignored) + iso.create_uv_iso_line().ok() + } else { + None + }; + + // move min/max points to isoParameter Line endPoints + let mut line_ivl = Extent1d::new(); + if surf_param == SurfParamType::U { + p_min.x = iso_parameter; + p_max.x = iso_parameter; + let _ = line_ivl.set_min_max(p_min.y, p_max.y); + } else { + p_min.y = iso_parameter; + p_max.y = iso_parameter; + let _ = line_ivl.set_min_max(p_min.x, p_max.x); + } + + // evaluate Line 3D endPoints + let st_pt = self.evaluate_point_fast(p_min); + let end_pt = self.evaluate_point_fast(p_max); + + // create the line + let mut line = Line::create_line_segment(3, st_pt, end_pt, None)?; + line.edit_parameterization(&line_ivl)?; + + Ok(PlaneIsoCurve { + curve: line, + max_gap_3d: 0.0, + uv_iso_curve: uv_curve, + }) + } + + /// Drops `curve` over `interval` onto the plane over `uv_domain` (`DropCurve`). + /// + /// A line (an `SmLine`, or a curve `IsLine` finds straight) gives the UV line of + /// its projection trimmed to the domain (none when it misses the domain or is + /// degenerate), kept when `keep_all` or its end points drop within + /// `approx_tol`; unless `creating_uv_trim_curve`, a trimmed line also trims the + /// curve interval. Otherwise a B-spline kind is trimmed to `interval` and its + /// control points are projected and clamped to the domain: the UV B-spline of + /// those points is exact when no clamp moves a point off its normal line by more + /// than `approx_tol`, and is kept when `keep_all` or every control point drops + /// within `approx_tol`. Everything else is the general `SmSurface::DropCurve`. + /// + /// # Errors + /// + /// Those of the curve evaluations and constructions; + /// [`SolidError::Unported`] for the general `SmSurface::DropCurve` + /// (`intersect.surface_drop_lib_p3`). + pub fn drop_curve( + &self, + k: &Kernel, + uv_domain: &Extent2d, + curve: &Curve, + interval: &Extent1d, + approx_tol: f64, + keep_all: bool, + creating_uv_trim_curve: bool, + ) -> Result { + // init output + let mut out = PlaneDropCurve { + max_drop_to_surf: 0.0, + max_approx_dev: 0.0, + uv_curves: Vec::new(), + }; + + // locals + let is_line = + matches!(curve.kind(), CurveKind::Line(_)) || curve.is_line(5, EFF_ZERO)?.is_some(); + let mut ivl = *interval; + + // Check the fairly trivial case of projecting a line to a plane. + if is_line { + // get 3d line endPts + let mut st_pnt_3d = curve.evaluate_point(ivl.min())?; + let mut end_pnt_3d = curve.evaluate_point(ivl.max())?; + + // Get Line 2d endPt projections to infinite plane + let mut st_pnt_2d = self.project_point_to_uv_domain(st_pnt_3d); + let mut end_pnt_2d = self.project_point_to_uv_domain(end_pnt_3d); + let vec_2d = end_pnt_2d - st_pnt_2d; + + // trim drop line to plane domain + let tol_u = approx_tol / self.uv_scale.x; // 3d tol to 2d + let tol_v = approx_tol / self.uv_scale.y; + let found = + uv_domain.intersect_with_infinite_line(st_pnt_2d, vec_2d, Some(tol_u), Some(tol_v)); + + // no DropCurve without UVDomain intersection + let Some(found) = found else { + return Ok(out); + }; + + // union the trimIvl with the line ivl + let line_ivl = Extent1d::from_min_max(0.0, 1.0); + let mut final_ivl = ivl; + let trim_ivl = found + .intersect(&line_ivl) + .unwrap_or_else(|_| Extent1d::new()); + if trim_ivl.is_init() { + return Ok(out); + } + + // adjust for partial drops + if !trim_ivl.are_equal_bounds(0.0, 1.0, EFF_ZERO) { + // reevaluate srf[UVPts] + end_pnt_2d = st_pnt_2d + trim_ivl.max() * vec_2d; // order dependent code + st_pnt_2d += trim_ivl.min() * vec_2d; + + if !creating_uv_trim_curve { + // reevaluate crv[ivl] + let lo = final_ivl.evaluate(trim_ivl.min()); + let hi = final_ivl.evaluate(trim_ivl.max()); + let _ = final_ivl.set_min_max(lo, hi); + + // reevaluate crv[endpts] + st_pnt_3d = curve.evaluate_point(final_ivl.min())?; + end_pnt_3d = curve.evaluate_point(final_ivl.max())?; + } + } + + // get srf[endPts] + let new_st_3d = self.evaluate_point_fast(st_pnt_2d); + let new_end_3d = self.evaluate_point_fast(end_pnt_2d); + + // Max drop distance to surface + let dist1 = new_st_3d.distance(st_pnt_3d); + let dist2 = new_end_3d.distance(end_pnt_3d); + out.max_drop_to_surf = max2(dist1, dist2); + + // when the drop curve is good enough - save it to the output + if keep_all || out.max_drop_to_surf <= approx_tol { + // build dropCurve as a UVline + let vector_2d = end_pnt_2d - st_pnt_2d; + let scale = vector_2d.length(); + + // skip degenerate solutions + if scale > EFF_ZERO { + // compose the UVTrimCurve - same cr3dCurve parameterization + let vector_2d = vector_2d.unitize()?; + let line_interval = Extent1d::from_min_max(0.0, 1.0); + let mut line_2d = Line::bounded( + Vec3::from(st_pnt_2d), + Vec3::from(vector_2d), + &line_interval, + &BoundedLineOptions { + scale, + dim: 2, + ..BoundedLineOptions::default() + }, + ); + line_2d.edit_parameterization(&final_ivl)?; + + // all done - set output and return + out.uv_curves.push(Curve::from(line_2d)); + out.max_approx_dev = 0.0; // the UVLine is an exact rep of the UVDropCurve + } + return Ok(out); + } + } + + // arrive here for all nonLine 3d curves + // when the curve is a BSpline Curve + if curve.is_kind_of(BSplineCurve::TYPE) { + let Some(b_spline) = b_spline_part(curve) else { + return surface_drop_curve(); + }; + + // copy and trim the original crv to the given interval + let mut crv_copy_3d = b_spline.clone(); + ignore_status(crv_copy_3d.trim(k, &mut ivl, TrimMode::Notify))?; // may snap ivl + + // get the BSpline representation of the curve + let c = crv_copy_3d.canonical()?; + let mut ctrl_pts = c.control_points.clone(); + + // loop locals + let mut max_drop_sq = 0.0; + + // for every control point + for cp in &mut ctrl_pts { + let p_3d = *cp; + + // project to infinite plane + let mut uv_pnt = self.project_point_to_uv_domain(p_3d); + + // clamp control points + uv_pnt = uv_domain.clamp_point(uv_pnt); + + // save largest control point drop + let on_srf_3d = self.evaluate_point_fast(uv_pnt); + let drop_to_surf_sq = on_srf_3d.distance_squared(p_3d); + if drop_to_surf_sq > max_drop_sq { + max_drop_sq = drop_to_surf_sq; + } + + // find out how far clamping moved the control point from the drop point + let plane_normal = self.evaluate_normal(); // unit normal + let (dev_from_srf_nrm_line, _) = line_point_distance(on_srf_3d, plane_normal, p_3d); + + // if clamping moves the control point - give up - pass the call along + if dev_from_srf_nrm_line > approx_tol { + return surface_drop_curve(); + } + + // save the dropped control point + *cp = Point3::new(uv_pnt.x, uv_pnt.y, 0.0); + } + + // arrive here when all control points drop nicely within the plane trim boundaries + if keep_all || max_drop_sq < approx_tol * approx_tol { + // build 2d UVDropCurve + let rational = b_spline.is_rational()?; + let uv_curve = BSplineCurve::create_canonical(&CanonicalData { + dim: 2, + degree: c.degree, + control_points: &ctrl_pts, + form: c.form, + knot_multiplicities: &c.knot_multiplicities, + knots: &c.knots, + knot_type: c.knot_type, + weights: if rational { Some(&c.weights) } else { None }, + trim: None, + })?; + + // set output + out.uv_curves.push(Curve::from(uv_curve)); + out.max_drop_to_surf = sqrt(max_drop_sq); + out.max_approx_dev = 0.0; // ControlPt projection produces an exact UVDropCurve + } + + // all done + return Ok(out); + } + + // else pass the call along to the general DropCurve method + surface_drop_curve() + } + + // ---- coincidence ------------------------------------------------------------------ + + /// Whether `other` coincides with the plane within `tol_3d` (`CoincidenceCheck`): + /// over both whole domains (`whole_surface`) or over any overlap. + /// + /// `other` must be planar; another plane must be parallel (within the angle that + /// moves this plane's far end by `tol_3d`) and through this plane's origin. For + /// whole surfaces the four corners must match and either `other` is bilinear or + /// five interior samples lie on the plane with parallel normals. For an overlap + /// of two planes, a corner of `other` must project inside this domain, an edge of + /// `other` must cross it over at least `tol_3d`, or this plane's middle must + /// project inside `other`'s domain. For an overlap with another surface, a + /// boundary curve of one must meet one of the other with matching normals and + /// in-plane second derivatives, or the middle of one must drop onto the other. + /// + /// # Errors + /// + /// Those of the evaluations of `other`; [`SolidError::Unported`] for a surface + /// that is not a plane (`SmSurface::IsPlanar`, `surface.surface_p7`) and the + /// unported callees of the overlap test. + pub fn coincidence_check( + &self, + k: &Kernel, + other: &Surface, + tol_3d: f64, + whole_surface: bool, + ) -> Result { + // init output + let mut res = Coincidence { + are_coincident: false, + max_distance: -1.0, + }; + + // low work - surfaces are the same + if let SurfaceKind::Plane(p) = other.kind() { + if core::ptr::eq(p, self) { + res.are_coincident = true; + res.max_distance = 0.0; + return Ok(res); + } + } + + // Quick check: other surface would have to be planar. + if !surface_is_planar(other, tol_3d)? { + return Ok(res); + } + + // locals + let mut dist_sq = 0.0; + let mut max_dist = -1.0; + + let domain0 = self.natural_uv_domain(); + let domain1 = other.natural_uv_domain(); + + let plane_pnt0 = self.position.origin(); + let plane_norm0 = self.position.z_axis(); + + // find an angle tolerance that makes a plane this size deviate by the given tol. + let size = Vec2::new( + self.anal_uv_domain.u_interval().length() * self.uv_scale.x, + self.anal_uv_domain.v_interval().length() * self.uv_scale.y, + ); + let ang_tol_deg = rad_to_deg(tol_3d / size.length()); + + // Special for planes: rule out cases where infinite planes don't coincide. + let other_plane = match other.kind() { + SurfaceKind::Plane(p) => Some(p), + _ => None, + }; + + if let Some(op) = other_plane { + let other_pos = op.position(); + + // Check normals. + let other_norm = other_pos.z_axis(); + if !other_norm.is_parallel_to(plane_norm0, ang_tol_deg) { + return Ok(res); + } + + // Check positions. + let dist = plane_point_distance(plane_pnt0, plane_norm0, other_pos.origin())?; + if dist > tol_3d { + return Ok(res); + } + } + + if whole_surface { + res.are_coincident = false; + + // First, all four corner points must match. + let mut corners0 = Vec::with_capacity(4); + let mut corners1 = Vec::with_capacity(4); + for ii in 0..2 { + for jj in 0..2 { + let (fi, fj) = (f64::from(ii), f64::from(jj)); + corners0.push(self.evaluate_point(domain0.evaluate(fi, fj))); + corners1.push(other.evaluate_point(domain1.evaluate(fi, fj))?); + } + } + + // All four points of other must match one of ours. + let tol_sq = tol_3d * tol_3d; + for c0 in &corners0 { + for c1 in &corners1 { + dist_sq = c0.distance_squared(*c1); + if dist_sq <= tol_sq { + break; // Found a match. + } + } + if dist_sq > tol_sq { + break; // this-plane point did not find a match. + } + } + + if dist_sq > tol_sq { + return Ok(res); // Some corner did not match. + } + + // If the other surface is a plane as well, we're done (bilinear suffices). + if other.is_bilinear() { + res.max_distance = sqrt(dist_sq); + res.are_coincident = true; + return Ok(res); + } + + // Match some points. Midpoint and four around, not exact. + let uvs = [ + Point2::new(0.51, 0.48), + Point2::new(0.27, 0.23), + Point2::new(0.27, 0.77), + Point2::new(0.72, 0.77), + Point2::new(0.72, 0.23), + ]; + for uv1 in uvs { + let pt1 = other.evaluate_point(uv1)?; + let dist = plane_point_distance(plane_pnt0, plane_norm0, pt1)?; + + if dist > max_dist { + max_dist = dist; + res.max_distance = dist; + } + + if dist > tol_3d { + return Ok(res); + } + + // Also check normals. + let norm1 = surface_evaluate_normal(other, uv1)?; + if !norm1.is_parallel_to(plane_norm0, ang_tol_deg) { + return Ok(res); + } + } + + // Still here -- must be coincident. + res.are_coincident = true; + return Ok(res); + } + + // Now, check for any coincident overlap. + if let Some(op) = other_plane { + return Ok(self.plane_overlap(op, &domain0, &domain1, tol_3d, res)); + } + + // Checking partial overlap, and the other surface is not an SmPlane. + self.surface_overlap(k, other, &domain0, &domain1, tol_3d, ang_tol_deg, res) + } + + /// The plane/plane overlap test of [`Plane::coincidence_check`] (two coplanar + /// rectangles). + fn plane_overlap( + &self, + op: &Self, + domain0: &Extent2d, + domain1: &Extent2d, + tol_3d: f64, + mut res: Coincidence, + ) -> Coincidence { + let mut other_uvs = Vec::with_capacity(5); + let mut other_extent = Extent2d::new(); + + for ii in 0..2 { + for jj in 0..2 { + // plane1 corners to plane2 distances + let uv1 = if ii == 0 { + domain1.evaluate(f64::from(ii), f64::from(jj)) + } else { + domain1.evaluate(f64::from(ii), f64::from(1 - jj)) // To go around in order. + }; + let pt1 = op.evaluate_point_fast(uv1); + let uv0 = self.project_point_to_uv_domain(pt1); + + // First check max distance, for the output value. + let pt0 = self.evaluate_point_fast(uv0); + let dist = pt1.distance(pt0); + + if dist > res.max_distance { + res.max_distance = dist; + } + + if dist > tol_3d { + // (Shouldn't happen.) + res.are_coincident = false; + return res; + } + + // Now check whether it's internal (not on boundary: negative tol). + if domain0.contains_point(uv0, -EFF_ZERO_SQRT) { + res.are_coincident = true; + return res; + } + + other_uvs.push(uv0); + other_extent.add_point(uv0); + } + } + + // Now do the bounding box check (negative tol: don't catch just-touching cases). + if other_extent.are_disjoint(domain0, -EFF_ZERO_SQRT) { + res.are_coincident = false; + return res; + } + + // Intersect the four sides of the other with our domain. + if let Some(&first) = other_uvs.first() { + other_uvs.push(first); + } + let unit_ivl = Extent1d::from_min_max(0.0, 1.0); + for pair in other_uvs.windows(2) { + let (Some(&a), Some(&b)) = (pair.first(), pair.get(1)) else { + continue; + }; + let vec = b - a; + if let Some(int_ivl) = domain0.intersect_with_infinite_line(a, vec, None, None) { + // Intersect it with the unit interval (the segment between the corners). + if let Ok(int_ivl) = unit_ivl.intersect(&int_ivl) { + if int_ivl.length() >= tol_3d { + res.are_coincident = true; + return res; + } + } + } + } + + // Either they're disjoint, or this plane is totally contained in the other. + // Test our midpoint. + let uv0 = domain0.evaluate(0.5, 0.5); + let pt0 = self.evaluate_point(uv0); + let uv1 = op.project_point_to_uv_domain(pt0); + + // Also check max distance, for the output value. + let pt1 = op.evaluate_point_fast(uv1); + let dist = pt1.distance(pt0); + + if dist > res.max_distance { + res.max_distance = dist; + } + + if dist > tol_3d { + // (Shouldn't happen.) + res.are_coincident = false; + return res; + } + + // Now check internal; if so, we're done. But not on boundary: negative tol. + if domain1.contains_point(uv1, -EFF_ZERO_SQRT) { + res.are_coincident = true; + return res; + } + + // Didn't find any overlap. + res.are_coincident = false; + res + } + + /// The overlap test of [`Plane::coincidence_check`] with a planar surface that is + /// not an `SmPlane`: boundary curve intersections, then mutual middle drops. + fn surface_overlap( + &self, + k: &Kernel, + other: &Surface, + domain0: &Extent2d, + domain1: &Extent2d, + tol_3d: f64, + ang_tol_deg: f64, + mut res: Coincidence, + ) -> Result { + // Create two sets of boundary curves. + let bdrys_3d0 = create_natural_uv_trim_curves(&Surface::from(self.clone()), domain0)?; + let bdrys_3d1 = create_natural_uv_trim_curves(other, domain1)?; + + // We'll be checking normals, and this plane's normal never changes. + let norm0 = self.position.z_axis(); + + // Also, our first derivatives never change. + let su0 = self.position.x_axis() * self.uv_scale.x; + let sv0 = self.position.y_axis() * self.uv_scale.y; + + // degenerate inner curves, computed once + let mut crv1_degen = Vec::with_capacity(bdrys_3d1.len()); + for c in &bdrys_3d1 { + crv1_degen.push(match c { + Some(c) => c.is_degenerate(EFF_ZERO, None)?, + None => false, + }); + } + + // out-of-plane test of the other surface's derivatives + let out_of_plane = |v: Vec3| norm0.dot(v).abs() > ang_tol_deg; + + // Set this True as default, so that we can just return if found. + res.are_coincident = true; + + for (ii, crv0) in bdrys_3d0.iter().enumerate() { + let Some(crv0) = crv0 else { continue }; + if crv0.is_degenerate(EFF_ZERO, None)? { + continue; + } + + let crv_dom0 = if ii == 0 || ii == 2 { + domain0.u_interval() + } else { + domain0.v_interval() + }; + + for (jj, crv1) in bdrys_3d1.iter().enumerate() { + let Some(crv1) = crv1 else { continue }; + if crv1_degen.get(jj).copied().unwrap_or(false) { + continue; + } + + let crv_dom1 = if jj == 0 || jj == 2 { + domain1.u_interval() + } else { + domain1.v_interval() + }; + + // Check for an intersection. + let sols = match crv0.global_curve_intersect( + k, + &crv_dom0, + crv1, + &crv_dom1, + tol_3d, + &CurveIntersectOptions::::default(), + ) { + Ok(s) => s, + Err(e) if e.is_unported() => return Err(e), + Err(_) => continue, + }; + if sols.is_empty() { + continue; + } + + for sol in sols.as_slice() { + // use an end point of the solution + let t0 = sol.start.parameters[0]; + let t1 = sol.start.parameters[1]; + + // Get the surface uv's from the edge curve params. + let (_uv0, uv_binorm0) = boundary_uv(domain0, ii, t0); + let (uv1, uv_binorm1) = boundary_uv(domain1, jj, t1); + let norm1 = surface_evaluate_normal(other, uv1)?; + + if !norm1.is_parallel_to(norm0, ang_tol_deg) { + continue; + } + + // Have to check 2nd order terms: cyl with seam in plane. + let d2 = evaluate_2nd_derivatives(other, uv1)?; + if out_of_plane(d2.du) + || out_of_plane(d2.dv) + || out_of_plane(d2.duu) + || out_of_plane(d2.duv) + || out_of_plane(d2.dvv) + { + continue; + } + + if sol.solution_type == SolutionType::SingleValue { + // If this hits the interior of both boundaries + if !crv_dom0.is_value_on_boundary(t0, EFF_ZERO).0 + && !crv_dom1.is_value_on_boundary(t1, EFF_ZERO).0 + { + return Ok(res); + } + } else { + // Range solution: edge-to-edge. Need to check binormals. + let binorm_3d0 = uv_binorm0.x * su0 + uv_binorm0.y * sv0; + let (_, su1, sv1) = evaluate_1st_derivatives(other, uv1)?; + let binorm_3d1 = uv_binorm1.x * su1 + uv_binorm1.y * sv1; + if binorm_3d0.dot(binorm_3d1) > 0.0 { + return Ok(res); + } + } + } + } + } + + // If there is coincidence, then one surface completely contains the other. + // Drop to this first because planes are easy. + let uv1 = domain1.mid(); + let pt1 = other.evaluate_point(uv1)?; + let (success, _uv0, dist) = surface_drop_point(&Surface::from(self.clone()), pt1, domain0)?; + + // Also set output argument: + if dist > res.max_distance { + res.max_distance = dist; + } + + if success && dist <= tol_3d { + // Point coincidence, check 2nd order terms, not just normals. + let d2 = evaluate_2nd_derivatives(other, uv1)?; + if in_plane(norm0, &d2, ang_tol_deg) { + return Ok(res); + } + } + + // Repeat the other way around. + let uv0 = domain0.mid(); + let pt0 = self.evaluate_point(uv0); + let (success, uv1, dist) = surface_drop_point(other, pt0, domain1)?; + + // Also set output argument: + if dist > res.max_distance { + res.max_distance = dist; + } + + if success && dist <= tol_3d { + let d2 = evaluate_2nd_derivatives(other, uv1)?; + if in_plane(norm0, &d2, ang_tol_deg) { + return Ok(res); + } + } + + // If we arrive here, we haven't found coincidence. + res.are_coincident = false; + Ok(res) + } +} + +/// `sm_IsGrazingIntersection`: whether the curve/line intersection at `curve_param` +/// / `line_param` is a graze, i.e. the tangents are parallel and the curve has +/// curvature there. +/// +/// # Errors +/// +/// Those of the curve evaluation (upstream ignores its status). +pub fn is_grazing_intersection( + curve: &Curve, + curve_param: f64, + line: &Line, + line_param: f64, +) -> Result { + // Method: check tangents. If parallel, then as long as the curve + // has any curvature, it's a graze. + let curve_eval = curve.evaluate(curve_param, 2, false, true)?; + let line_eval = line.evaluate(line_param, 1); + let c1 = curve_eval.get(1).copied().unwrap_or(Vec3::ZERO); + let c2 = curve_eval.get(2).copied().unwrap_or(Vec3::ZERO); + let l1 = line_eval.get(1).copied().unwrap_or(Vec3::ZERO); + if !c1.is_parallel_to(l1, EFF_ZERO_DEG) { + return Ok(false); + } + + // Check curvature. If the 2nd deriv has a component that's not parallel + // to the 1st deriv, there is curvature. + let cross = c1.cross(c2); + Ok(cross.length_squared() > EFF_ZERO_SQ) +} + +// ---- helpers ------------------------------------------------------------------------------ + +/// A solution handle naming nothing (the curve/curve solutions of +/// `CoincidenceCheck` only use their parameters). +#[derive(Debug, Clone, Copy, PartialEq)] +struct NoObject; + +impl SolutionObject for NoObject { + fn kind(&self) -> ObjectKind { + ObjectKind::Curve + } +} + +/// The uv of parameter `t` on boundary `index` of `domain` (0: v min, 1: u max, +/// 2: v max, 3: u min) and the inward binormal of that boundary. +fn boundary_uv(domain: &Extent2d, index: usize, t: f64) -> (Point2, Vec2) { + match index { + 0 => (Point2::new(t, domain.v_min()), Vec2::new(0.0, 1.0)), + 1 => (Point2::new(domain.u_max(), t), Vec2::new(-1.0, 0.0)), + 2 => (Point2::new(t, domain.v_max()), Vec2::new(0.0, -1.0)), + 3 => (Point2::new(domain.u_min(), t), Vec2::new(1.0, 0.0)), + // the switch upstream leaves the values unset; never more than 4 boundaries + _ => (Point2::new(t, domain.v_min()), Vec2::new(0.0, 0.0)), + } +} + +/// The second-order derivatives of `Evaluate2ndDerivatives`. +struct SecondDerivatives { + du: Vec3, + dv: Vec3, + duv: Vec3, + duu: Vec3, + dvv: Vec3, +} + +/// Every derivative of `d2` lies in the plane of normal `norm0` within `ang_tol`. +fn in_plane(norm0: Vec3, d2: &SecondDerivatives, ang_tol: f64) -> bool { + norm0.dot(d2.du).abs() < ang_tol + && norm0.dot(d2.dv).abs() < ang_tol + && norm0.dot(d2.duu).abs() < ang_tol + && norm0.dot(d2.duv).abs() < ang_tol + && norm0.dot(d2.dvv).abs() < ang_tol +} + +/// `SmSurface::Evaluate1stDerivatives(uv, TRUE, TRUE, ..)` (co-ported from +/// `surface.surface_p1`): `Evaluate(uv, 1, 1, TRUE, TRUE, TRUE, .., TRUE)`. +fn evaluate_1st_derivatives(s: &Surface, uv: Point2) -> Result<(Point3, Vec3, Vec3)> { + let m = s.evaluate(uv, 1, 1, upper_half_flags())?; + let at = |i: usize, j: usize| { + m.get(i) + .and_then(|r| r.get(j)) + .copied() + .unwrap_or(Vec3::ZERO) + }; + Ok((at(0, 0), at(1, 0), at(0, 1))) +} + +/// `SmSurface::Evaluate2ndDerivatives(uv, TRUE, TRUE, ..)` (co-ported from +/// `surface.surface_p1`): `Evaluate(uv, 2, 2, TRUE, TRUE, TRUE, .., TRUE)`. +fn evaluate_2nd_derivatives(s: &Surface, uv: Point2) -> Result { + let m = s.evaluate(uv, 2, 2, upper_half_flags())?; + let at = |i: usize, j: usize| { + m.get(i) + .and_then(|r| r.get(j)) + .copied() + .unwrap_or(Vec3::ZERO) + }; + Ok(SecondDerivatives { + du: at(1, 0), + dv: at(0, 1), + duv: at(1, 1), + duu: at(2, 0), + dvv: at(0, 2), + }) +} + +/// From the left in both directions, upper half, non-zero tangents. +fn upper_half_flags() -> EvaluateFlags { + EvaluateFlags { + u_side: Side::Left, + v_side: Side::Left, + only_upper_half: true, + non_zero_tangents: true, + } +} + +/// The `SmBSplineCurve` part of a curve of a B-spline kind (upstream's slicing copy +/// `SmBSplineCurve(crBSplineCurve)`). +fn b_spline_part(curve: &Curve) -> Option<&BSplineCurve> { + match curve.kind() { + CurveKind::BSpline(b) => Some(b), + CurveKind::Line(l) => Some(l.base()), + CurveKind::Ellipse(e) => Some(e.base()), + CurveKind::Hyperbola(h) => Some(h.base()), + CurveKind::Parabola(p) => Some(p.base()), + CurveKind::Hermite(_) + | CurveKind::Conic(_) + | CurveKind::Projected(_) + | CurveKind::Iso(_) + | CurveKind::Offset(_) + | CurveKind::CrvInVolume(_) + | CurveKind::CrvOnSurf(_) + | CurveKind::Composite(_) => None, + } +} + +/// Transposes the `num_rows` x `len / num_rows` row-major array `a` in place. +fn transpose(a: &mut [T], num_rows: usize) { + if num_rows < 1 { + return; + } + let num_columns = a.len() / num_rows; + let temp = a.to_vec(); + for ii in 0..num_rows { + for jj in 0..num_columns { + if let (Some(dst), Some(&src)) = ( + a.get_mut(ii * num_columns + jj), + temp.get(jj * num_rows + ii), + ) { + *dst = src; + } + } + } +} + +// ---- unported callees --------------------------------------------------------------------- + +/// `crOther.IsPlanar(tol)`: a plane is planar; other kinds run `SmSurface::IsPlanar`. +fn surface_is_planar(s: &Surface, _tol: f64) -> Result { + match s.kind() { + SurfaceKind::Plane(_) => Ok(true), + SurfaceKind::BSpline(_) | SurfaceKind::CurveBounded(_) => { + // UNPORTED(surface.surface_p7): SmSurface::IsPlanar + Err(SolidError::unported( + "SmSurface::IsPlanar", + "surface.surface_p7", + )) + } + } +} + +/// `crOther.EvaluateNormal(uv, TRUE, TRUE, ..)`: the plane override; other kinds run +/// `SmSurface::EvaluateNormal`. +fn surface_evaluate_normal(s: &Surface, _uv: Point2) -> Result { + match s.kind() { + SurfaceKind::Plane(p) => Ok(p.evaluate_normal()), + SurfaceKind::BSpline(_) | SurfaceKind::CurveBounded(_) => { + // UNPORTED(surface.surface_p7): SmSurface::EvaluateNormal + Err(SolidError::unported( + "SmSurface::EvaluateNormal", + "surface.surface_p7", + )) + } + } +} + +/// `SmSurface::CreateNaturalUVTrimCurves(ctx, domain, SM_SP_V, FALSE, ..)`: the 3D +/// boundary curves. +fn create_natural_uv_trim_curves(_s: &Surface, _domain: &Extent2d) -> Result>> { + // UNPORTED(surface.surface_p6): SmSurface::CreateNaturalUVTrimCurves + Err(SolidError::unported( + "SmSurface::CreateNaturalUVTrimCurves", + "surface.surface_p6", + )) +} + +/// `SmSurface::DropPoint(pt, domain, NULL, bSuccess, uv, dist, bIsMulti, +/// SM_SO_NORMALIZE)`: success, uv and distance. +fn surface_drop_point( + _s: &Surface, + _pt: Point3, + _domain: &Extent2d, +) -> Result<(bool, Point2, f64)> { + // UNPORTED(surface.surface_p5): SmSurface::DropPoint + Err(SolidError::unported( + "SmSurface::DropPoint", + "surface.surface_p5", + )) +} + +/// The general `SmSurface::DropCurve`. +fn surface_drop_curve() -> Result { + // UNPORTED(intersect.surface_drop_lib_p3): SmSurface::DropCurve + Err(SolidError::unported( + "SmSurface::DropCurve", + "intersect.surface_drop_lib_p3", + )) +} + +/// The general `SmSurface::GlobalLineIntersect` (through the surface cache). +fn surface_global_line_intersect() -> Result> { + // UNPORTED(surface.surface_p8): SmSurface::GlobalLineIntersect + Err(SolidError::unported( + "SmSurface::GlobalLineIntersect", + "surface.surface_p8", + )) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn unit_plane() -> Plane { + Plane::new( + Point3::new(1.0, 2.0, 3.0), + Vec3::new(1.0, 0.0, 0.0), + Vec3::new(0.0, 1.0, 0.0), + Vec2::new(2.0, 3.0), + &Extent2d::from_bounds(0.0, 0.0, 1.0, 1.0), + ) + } + + #[test] + fn evaluate_and_project() { + let p = unit_plane(); + let pt = p.evaluate_point(Point2::new(0.5, 0.5)); + assert_eq!(pt, Point3::new(2.0, 3.5, 3.0)); + // clamped + let pt = p.evaluate_point(Point2::new(2.0, -1.0)); + assert_eq!(pt, Point3::new(3.0, 2.0, 3.0)); + let uv = p.project_point_to_uv_domain(Point3::new(2.0, 3.5, 7.0)); + assert_eq!(uv, Point2::new(0.5, 0.5)); + let d = p.evaluate(Point2::new(0.2, 0.3), 2, 2, false).unwrap(); + assert_eq!(d[1][0], Vec3::new(2.0, 0.0, 0.0)); + assert_eq!(d[0][1], Vec3::new(0.0, 3.0, 0.0)); + assert_eq!(d[1][1], Vec3::ZERO); + assert!(p.evaluate(Point2::new(0.0, 0.0), 2, 1, true).is_err()); + assert_eq!(p.evaluate_normal(), Vec3::new(0.0, 0.0, 1.0)); + } + + #[test] + fn nurb_and_queries() { + let mut p = unit_plane(); + assert!(p.base().gw_nurb().is_none()); + assert_eq!( + p.natural_uv_domain(), + Extent2d::from_bounds(0.0, 0.0, 1.0, 1.0) + ); + assert!(p.base().gw_nurb().is_none()); + p.make_nurb().unwrap(); + assert!(p.base().is_bilinear()); + assert!(p.is_kind_of(Plane::TYPE).unwrap()); + assert!(p.is_kind_of(BSplineSurface::TYPE).unwrap()); + assert!(p.is_bounded()); + assert!(!Plane::from_normal(Point3::ZERO, Vec3::new(0.0, 0.0, 2.0)).is_bounded()); + assert!(p.approx_eq(&p.copy())); + } + + #[test] + fn drop_point_and_line() { + let p = unit_plane(); + let dom = p.step_uv_domain(); + let sols = p + .drop_point_fast::( + &dom, + SolverOperation::Minimize, + Point3::new(2.0, 3.5, 5.0), + 1e-6, + None, + None, + ) + .unwrap(); + assert_eq!(sols.len(), 1); + assert_eq!(sols.as_slice()[0].start.solution_value, 2.0); + let sols = p + .global_line_intersect::( + &dom, + Point3::new(2.0, 3.5, 5.0), + Vec3::new(0.0, 0.0, -1.0), + None, + false, + 1e-6, + ) + .unwrap(); + assert_eq!(sols.len(), 1); + assert_eq!(sols.as_slice()[0].start.parameters[0], 2.0); + assert!(p + .drop_point_fast::( + &dom, + SolverOperation::Maximize, + Point3::ZERO, + 1e-6, + None, + None + ) + .is_err()); + } + + #[test] + fn toggle_and_trim() { + let mut p = unit_plane(); + let before = p.evaluate_point(Point2::new(0.25, 0.75)); + p.toggle_swap_uv_bit(); + let after = p.evaluate_point(Point2::new(0.75, 0.25)); + assert!(before.distance(after) < 1e-12); + let p = unit_plane(); + let (a, b) = p + .trim_plane_line_to_plane_domain( + &p.step_uv_domain(), + Point3::new(0.0, 3.0, 3.0), + Point3::new(5.0, 3.0, 3.0), + 0.0, + ) + .unwrap(); + assert!(a.distance(Point3::new(1.0, 3.0, 3.0)) < 1e-12); + assert!(b.distance(Point3::new(3.0, 3.0, 3.0)) < 1e-12); + } + + #[test] + fn coincidence_of_planes() { + let k = Kernel::default(); + let p = unit_plane(); + let q = Surface::from(Plane::new( + Point3::new(1.5, 2.0, 3.0), + Vec3::new(1.0, 0.0, 0.0), + Vec3::new(0.0, 1.0, 0.0), + Vec2::new(2.0, 3.0), + &Extent2d::from_bounds(0.0, 0.0, 1.0, 1.0), + )); + let c = p.coincidence_check(&k, &q, 1e-6, false).unwrap(); + assert!(c.are_coincident); + let c = p.coincidence_check(&k, &q, 1e-6, true).unwrap(); + assert!(!c.are_coincident); + let b = Surface::from(p.base_with_nurb().unwrap().into_owned()); + assert!(p + .coincidence_check(&k, &b, 1e-6, true) + .unwrap_err() + .is_unported()); + } +} diff --git a/crates/solidcore/src/surface/surface/p2.rs b/crates/solidcore/src/surface/surface/p2.rs index 22026807fc..5b706920de 100644 --- a/crates/solidcore/src/surface/surface/p2.rs +++ b/crates/solidcore/src/surface/surface/p2.rs @@ -64,9 +64,13 @@ //! Deviations: //! - **Object model.** `SmSurface` is not abstract upstream, but every ported surface //! is a derived class: the [`SurfaceKind`] variants. The ported kinds are -//! [`BSplineSurface`] and [`CurveBoundedSurface`] (unit -//! `surface.curve_bounded_surface`); the analytic and generated surfaces (`SmPlane`, -//! `SmCone`, ...) join the enum in their own units. Each virtual method is one `match`: a +//! [`BSplineSurface`], [`CurveBoundedSurface`] (unit +//! `surface.curve_bounded_surface`) and [`Plane`] (unit `surface.plane_p1`: the +//! inherited `SmBSplineSurface` methods run on its B-spline part, re-dispatched to +//! the plane's overrides; `Transform` and `TrimWithDomain` belong to +//! `surface.plane_p2`, `STEPInversion` needs the point solvers of +//! `surface.surface_p1`); the other analytic and generated surfaces (`SmCone`, ...) +//! join the enum in their own units. Each virtual method is one `match`: a //! kind that overrides it calls its own method, the others run the base-class body //! ported here. The base bodies are also public as `base_*` functions (they are //! what a kind without an override runs, and what difftest compares with an @@ -165,6 +169,7 @@ use crate::nurbs::b_spline_surface_n_lib::p2::{EvaluateFlags, OrientType, Skinne use crate::nurbs::crv_fit::p1::ParamMethod; use crate::nurbs::knots::Side; use crate::surface::curve_bounded_surface::CurveBoundedSurface; +use crate::surface::plane::Plane; use crate::topology::database_io::DatabaseReader; // ---- type codes --------------------------------------------------------------------- @@ -232,6 +237,8 @@ pub enum SurfaceKind { BSpline(BSplineSurface), /// `SmCurveBoundedSurface`. CurveBounded(CurveBoundedSurface), + /// `SmPlane` (an `SmBSplineSurface`). + Plane(Plane), } /// A surface (`SmSurface`): its concrete kind and the object owning it (`m_pOwner`: @@ -258,6 +265,12 @@ impl From for Surface { } } +impl From for Surface { + fn from(s: Plane) -> Self { + Self::new(SurfaceKind::Plane(s)) + } +} + /// The curves of a surface/surface intersection (`GlobalSurfaceIntersect`'s /// outputs): one entry per intersection curve in each array. #[derive(Debug, Clone, Default)] @@ -401,6 +414,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(_) => BSplineSurface::TYPE, SurfaceKind::CurveBounded(s) => s.type_code(), + SurfaceKind::Plane(s) => s.type_code(), } } @@ -410,6 +424,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.type_string(), SurfaceKind::CurveBounded(s) => s.type_string(), + SurfaceKind::Plane(s) => s.type_string(), } } @@ -419,6 +434,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.class_string(), SurfaceKind::CurveBounded(s) => s.class_string(), + SurfaceKind::Plane(s) => s.class_string(), } } @@ -431,6 +447,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.is_kind_of(t), SurfaceKind::CurveBounded(s) => Ok(s.is_kind_of(t)), + SurfaceKind::Plane(s) => s.is_kind_of(t), } } @@ -445,6 +462,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => Ok(Self::from(s.copy())), SurfaceKind::CurveBounded(_) => base_copy(), + SurfaceKind::Plane(s) => Ok(Self::from(s.copy())), } } @@ -457,6 +475,8 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => Ok(Self::from(s.copy_and_add_analytics()?)), SurfaceKind::CurveBounded(_) => base_copy_and_add_analytics(), + // SmBSplineSurface::CopyAndAddAnalytics: not SmBSplineSurface_TYPE, so Copy + SurfaceKind::Plane(s) => Ok(Self::from(s.copy())), } } @@ -478,6 +498,9 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.evaluate(uv, highest_u_deriv, highest_v_deriv, flags), SurfaceKind::CurveBounded(s) => s.evaluate(uv, highest_u_deriv, highest_v_deriv, flags), + SurfaceKind::Plane(s) => { + s.evaluate(uv, highest_u_deriv, highest_v_deriv, flags.only_upper_half) + } } } @@ -490,6 +513,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.evaluate_point(uv), SurfaceKind::CurveBounded(s) => s.evaluate_point(uv), + SurfaceKind::Plane(s) => Ok(s.evaluate_point(uv)), } } @@ -501,14 +525,18 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.natural_uv_domain(), SurfaceKind::CurveBounded(s) => s.natural_uv_domain(), + SurfaceKind::Plane(s) => s.natural_uv_domain(), } } - /// The STEP parameter domain (`GetSTEPUVDomain`; the base default, the natural - /// domain, for every ported kind). + /// The STEP parameter domain (`GetSTEPUVDomain`; the plane's analytic domain, + /// else the base default, the natural domain). #[must_use] pub fn step_uv_domain(&self) -> Extent2d { - base_step_uv_domain(self) + match &self.kind { + SurfaceKind::Plane(s) => s.step_uv_domain(), + SurfaceKind::BSpline(_) | SurfaceKind::CurveBounded(_) => base_step_uv_domain(self), + } } /// The degree in `param`'s direction (`GetDegree`). @@ -517,6 +545,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.degree(param), SurfaceKind::CurveBounded(_) => base_degree(), + SurfaceKind::Plane(s) => s.base_for_query().degree(param), } } @@ -527,6 +556,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.number_control_points(param), SurfaceKind::CurveBounded(_) => base_number_control_points(), + SurfaceKind::Plane(s) => s.base_for_query().number_control_points(param), } } @@ -539,6 +569,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.max_analytic_domain(), SurfaceKind::CurveBounded(_) => Ok(base_max_analytic_domain()), + SurfaceKind::Plane(s) => Ok(s.max_analytic_domain()), } } @@ -548,6 +579,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.is_bilinear(), SurfaceKind::CurveBounded(_) => base_is_bilinear(), + SurfaceKind::Plane(s) => s.base_for_query().is_bilinear(), } } @@ -560,6 +592,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.is_parallel_to_vector(vector), SurfaceKind::CurveBounded(_) => Ok(base_is_parallel_to_vector()), + SurfaceKind::Plane(s) => Ok(s.is_parallel_to_vector(vector)), } } @@ -577,6 +610,7 @@ impl Surface { match &self.kind { SurfaceKind::BSpline(s) => s.knots(param, ivl), SurfaceKind::CurveBounded(_) => base_knots(), + SurfaceKind::Plane(s) => s.base_for_query().knots(param, ivl), } } @@ -614,25 +648,43 @@ impl Surface { s.step_inversion(anal_domain, point_on_surf, tol_3d, uv_guess) } SurfaceKind::CurveBounded(_) => base_step_inversion(), + // SmBSplineSurface::STEPInversion solves on the plane through the virtual + // point solvers + // UNPORTED(surface.surface_p1): SmSurface::GlobalPointSolve + SurfaceKind::Plane(_) => Err(SolidError::unported( + "SmSurface::GlobalPointSolve", + "surface.surface_p1", + )), } } - /// `DropPointFast`: no ported kind overrides it; the base default fails. + /// `DropPointFast`: the plane override (its solutions name no object); the + /// other ported kinds run the base default, which fails. /// /// # Errors /// - /// `SM_ERR` (the base default). + /// Those of [`Plane::drop_point_fast`]; `SM_ERR` (the base default). pub fn drop_point_fast( &self, - _uv_domain: &Extent2d, - _operation: SolverOperation, - _test_point: Point3, + uv_domain: &Extent2d, + operation: SolverOperation, + test_point: Point3, _in_pointing_vector: Option, - _distance_tolerance: f64, - _target_distance: Option, + distance_tolerance: f64, + target_distance: Option, _requested: SolutionRequested, ) -> Result> { - base_drop_point_fast() + match &self.kind { + SurfaceKind::Plane(s) => s.drop_point_fast( + uv_domain, + operation, + test_point, + distance_tolerance, + target_distance, + None, + ), + SurfaceKind::BSpline(_) | SurfaceKind::CurveBounded(_) => base_drop_point_fast(), + } } /// `IntersectWithPlane`: no ported kind overrides it; the base default fails. @@ -665,6 +717,7 @@ impl Surface { match &mut self.kind { SurfaceKind::BSpline(s) => s.adjust_step_uv_domain(new_step_uv_domain), SurfaceKind::CurveBounded(_) => base_adjust_step_uv_domain(), + SurfaceKind::Plane(s) => s.adjust_step_uv_domain(new_step_uv_domain), } } @@ -677,6 +730,7 @@ impl Surface { match &mut self.kind { SurfaceKind::BSpline(s) => s.reverse(param), SurfaceKind::CurveBounded(_) => base_edit(), + SurfaceKind::Plane(s) => s.reverse(param), } } @@ -689,6 +743,7 @@ impl Surface { match &mut self.kind { SurfaceKind::BSpline(s) => s.reparameterize(new_domain), SurfaceKind::CurveBounded(_) => base_edit(), + SurfaceKind::Plane(s) => s.reparameterize(new_domain), } } @@ -701,6 +756,7 @@ impl Surface { match &mut self.kind { SurfaceKind::BSpline(s) => s.swap_uv(), SurfaceKind::CurveBounded(_) => base_edit(), + SurfaceKind::Plane(s) => s.swap_uv(), } } @@ -713,6 +769,11 @@ impl Surface { match &mut self.kind { SurfaceKind::BSpline(s) => s.transform(rotate_n_move, scale), SurfaceKind::CurveBounded(_) => base_edit(), + // UNPORTED(surface.plane_p2): SmPlane::Transform + SurfaceKind::Plane(_) => Err(SolidError::unported( + "SmPlane::Transform", + "surface.plane_p2", + )), } } @@ -725,6 +786,11 @@ impl Surface { match &mut self.kind { SurfaceKind::BSpline(s) => s.trim_with_domain(trim_domain), SurfaceKind::CurveBounded(_) => base_edit(), + // UNPORTED(surface.plane_p2): SmPlane::TrimWithDomain + SurfaceKind::Plane(_) => Err(SolidError::unported( + "SmPlane::TrimWithDomain", + "surface.plane_p2", + )), } } @@ -743,6 +809,10 @@ impl Surface { Ok((Self::from(l), Self::from(r))) } SurfaceKind::CurveBounded(_) => base_split_at(), + SurfaceKind::Plane(s) => { + let (l, r) = s.base_for_query().split_at(param, surf_param)?; + Ok((Self::from(l), Self::from(r))) + } } } @@ -761,6 +831,10 @@ impl Surface { s.create_extended_surface(dist, extension_continuity)?, )), SurfaceKind::CurveBounded(_) => base_create_extended_surface(), + SurfaceKind::Plane(s) => Ok(Self::from( + s.base_for_query() + .create_extended_surface(dist, extension_continuity)?, + )), } } @@ -783,6 +857,13 @@ impl Surface { extension_continuity, )?)), SurfaceKind::CurveBounded(_) => base_create_extended_surface(), + SurfaceKind::Plane(s) => { + Ok(Self::from(s.base_for_query().create_extended_surface_dir( + ext_direction, + dist, + extension_continuity, + )?)) + } } } diff --git a/crates/solidcore/src/surface/surface_cache/p1.rs b/crates/solidcore/src/surface/surface_cache/p1.rs index 5afe5ad60f..6f565fa5f3 100644 --- a/crates/solidcore/src/surface/surface_cache/p1.rs +++ b/crates/solidcore/src/surface/surface_cache/p1.rs @@ -174,11 +174,24 @@ fn invalid(operation: &'static str, reason: &'static str) -> SolidError { SolidError::InvalidInput { operation, reason } } +const OP_PLANE_ISO: &str = "surface::surface_cache::p1::create_iso_parametric_curve"; +const OP_PLANE_BOX: &str = "surface::surface_cache::p1::calculate_bounding_box"; + +/// A surface cache operation on an `SmPlane`, which the cache code does not handle. +const fn plane_unsupported(operation: &'static str) -> SolidError { + SolidError::Unsupported { + operation, + reason: "SmPlane surfaces in the surface cache", + } +} + /// `SM_CAST_PTR(SmBSplineSurface, surface)`. const fn bspline_of(surface: &Surface) -> Option<&BSplineSurface> { match surface.kind() { SurfaceKind::BSpline(b) => Some(b), - SurfaceKind::CurveBounded(_) => None, + // an SmPlane is an SmBSplineSurface upstream, but the cache code here runs the + // B-spline methods without the plane's overrides: refused + SurfaceKind::CurveBounded(_) | SurfaceKind::Plane(_) => None, } } @@ -213,6 +226,9 @@ fn create_iso_parametric_curve( ) -> Result { match surface.kind() { SurfaceKind::BSpline(b) => bspline_iso_curve(k, b, param, iso, domain), + // SmPlane::CreateIsoParametricCurve makes an SmLine, which the cache code here + // cannot hold as a B-spline + SurfaceKind::Plane(_) => Err(plane_unsupported(OP_PLANE_ISO)), SurfaceKind::CurveBounded(_) => { // UNPORTED(surface.surface_p5): SmSurface::CreateIsoParametricCurve Err(SolidError::unported( @@ -247,6 +263,8 @@ fn calculate_bounding_box( ) -> Result { match surface.kind() { SurfaceKind::BSpline(b) => b.calculate_bounding_box(domain, req), + // the plane branch of SmBSplineSurface::CalculateBoundingBox is not ported + SurfaceKind::Plane(_) => Err(plane_unsupported(OP_PLANE_BOX)), SurfaceKind::CurveBounded(_) => { // UNPORTED(surface.surface_p1): SmSurface::CalculateBoundingBox Err(SolidError::unported( diff --git a/fixtures/surface.plane_p1/upstream.json b/fixtures/surface.plane_p1/upstream.json new file mode 100644 index 0000000000..dff2873f20 --- /dev/null +++ b/fixtures/surface.plane_p1/upstream.json @@ -0,0 +1,1990 @@ +{ + "cases": [ + { + "name": "section_plane_adjust", + "upstream_ref": "tests/prog_test/src/smSurfaceTest.cpp:716", + "inputs": { + "make": { + "kind": "normal", + "o": [ + 1, + 2, + 3 + ], + "n": [ + 0.3, + 0.4, + 0.8660254037844386 + ] + }, + "ops": [ + { + "op": "state" + }, + { + "op": "adjust", + "dom": { + "explicit": [ + -5, + -5, + 5, + 5 + ] + } + }, + { + "op": "state" + }, + { + "op": "drop", + "dom": "step", + "sop": 5, + "p": [ + 2, + 2, + 9 + ], + "tol": 0.001 + }, + { + "op": "drop", + "dom": "step", + "sop": 3, + "p": [ + 40, + 2, + 9 + ], + "tol": 0.001 + }, + { + "op": "inherited", + "v": [ + 0.3, + 0.4, + 0.8660254037844386 + ] + }, + { + "op": "queries", + "uv": [ + 0.5, + 0.5 + ] + } + ] + } + }, + { + "name": "curve_test_plane", + "upstream_ref": "tests/prog_test/src/smCurveTest.cpp:7296", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + }, + "ops": [ + { + "op": "evaluate", + "uv": [ + 3, + 4 + ], + "hu": 2, + "hv": 2, + "upper": true + }, + { + "op": "evaluate", + "uv": [ + -3, + 14 + ], + "hu": 1, + "hv": 3 + }, + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "segment", + "a": [ + 1, + 1, + 5 + ], + "b": [ + 9, + 8, + -1 + ] + }, + "tol": 0.001, + "keep_all": true + }, + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "segment", + "a": [ + -5, + 1, + 2 + ], + "b": [ + 15, + 8, + 2 + ] + }, + "tol": 0.001 + }, + { + "op": "iso", + "iso": 4, + "want_uv": true + }, + { + "op": "iso", + "v_dir": true, + "iso": 7, + "want_uv": true + }, + { + "op": "iso", + "iso": 4, + "domain": [ + 1, + 2, + 3, + 6 + ] + }, + { + "op": "state" + } + ] + } + }, + { + "name": "curve_test_plane_creating_fallback", + "upstream_ref": "tests/prog_test/src/smCurveTest.cpp:7296 (falls back to SmSurface::DropCurve)", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + }, + "ops": [ + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "segment", + "a": [ + -5, + 1, + 2 + ], + "b": [ + 15, + 8, + 2 + ] + }, + "tol": 0.001, + "creating": true + } + ] + } + }, + { + "name": "merge_test_canonical", + "upstream_ref": "tests/prog_test/src/smMergeTest.cpp:605", + "inputs": { + "make": { + "kind": "canonical", + "o": [ + 20, + 15, + 0 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ] + }, + "ops": [ + { + "op": "inherited", + "v": [ + 0, + 0, + 1 + ] + }, + { + "op": "inherited", + "v": [ + 1, + 0, + 0 + ] + }, + { + "op": "iso", + "iso": 5, + "domain": [ + 0, + 0, + 5, + 5 + ], + "want_uv": true + }, + { + "op": "line", + "dom": { + "explicit": [ + 0, + 0, + 5, + 5 + ] + }, + "p": [ + 22, + 16, + 4 + ], + "v": [ + 0, + 0, + -1 + ], + "tol": 1e-06 + }, + { + "op": "copy" + }, + { + "op": "eq", + "other": { + "kind": "canonical", + "o": [ + 20, + 15, + 0 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ] + } + } + ] + } + }, + { + "name": "general_xy_plane", + "upstream_ref": "tests/SM_API_test/src/TestSmGeneral.cpp:1537", + "inputs": { + "make": { + "kind": "normal", + "o": [ + 0, + 0, + 0 + ], + "n": [ + 0, + 0, + 1 + ] + }, + "ops": [ + { + "op": "queries", + "uv": [ + 0, + 0 + ] + }, + { + "op": "kind_of", + "t": 15011 + }, + { + "op": "kind_of", + "t": 15002 + }, + { + "op": "kind_of", + "t": 15001 + }, + { + "op": "kind_of", + "t": 15013 + }, + { + "op": "project", + "p": [ + 3, + -2, + 7 + ] + }, + { + "op": "normal", + "uv": [ + 0, + 0 + ] + }, + { + "op": "eq", + "other": { + "kind": "normal", + "o": [ + 0, + 0, + 0 + ], + "n": [ + 0, + 0, + 1 + ] + } + }, + { + "op": "eq", + "other": { + "kind": "normal", + "o": [ + 0, + 0, + 1e-12 + ], + "n": [ + 0, + 0, + 1 + ] + } + } + ] + } + }, + { + "name": "error_codes_unit_square", + "upstream_ref": "tests/SM_API_test/src/TestSmErrorCodes.cpp:89", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 0 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 1, + 1 + ] + }, + "ops": [ + { + "op": "line", + "dom": "step", + "p": [ + 0.5, + 0.5, + 1 + ], + "v": [ + 0, + 0, + -1 + ], + "tol": 1e-06 + }, + { + "op": "line", + "dom": "step", + "p": [ + 0.5, + 0.5, + 1 + ], + "v": [ + 0, + 0, + 1 + ], + "ray": true, + "tol": 1e-06 + }, + { + "op": "line", + "dom": "step", + "p": [ + 2, + 0.5, + 1 + ], + "v": [ + 0, + 0, + -1 + ], + "tol": 1e-06 + }, + { + "op": "line", + "dom": "step", + "p": [ + -1, + 0.5, + 0 + ], + "v": [ + 1, + 0, + 0 + ], + "tol": 1e-06 + }, + { + "op": "line", + "dom": "step", + "p": [ + -1, + 0.5, + 0 + ], + "v": [ + 1, + 0, + 0 + ], + "ivl": [ + 0.5, + 1.5 + ], + "tol": 1e-06 + }, + { + "op": "line", + "dom": "step", + "p": [ + -1, + 0.5, + 0 + ], + "v": [ + 1, + 0, + 0 + ], + "ray": true, + "tol": 1e-06 + }, + { + "op": "line", + "dom": "step", + "p": [ + -1, + 0.5, + 0.1 + ], + "v": [ + 1, + 0, + 0 + ], + "tol": 1e-06 + }, + { + "op": "drop", + "dom": "step", + "sop": 0, + "p": [ + 0.5, + 0.5, + 1e-07 + ], + "tol": 1e-06 + }, + { + "op": "drop", + "dom": "step", + "sop": 0, + "p": [ + 0.5, + 0.5, + 0.001 + ], + "tol": 1e-06 + }, + { + "op": "drop", + "dom": "step", + "sop": 5, + "p": [ + 1.5, + 0.5, + 0 + ], + "tol": 1e-06 + }, + { + "op": "drop", + "dom": "step", + "sop": 5, + "p": [ + 1.0000005, + 0.5, + 0 + ], + "tol": 1e-06 + }, + { + "op": "drop", + "dom": "step", + "sop": 3, + "p": [ + 0.2, + 0.5, + 3 + ], + "tol": 1e-06, + "target": 2.0 + }, + { + "op": "drop", + "dom": "step", + "sop": 4, + "p": [ + 0.2, + 0.5, + 3 + ], + "tol": 1e-06 + } + ] + } + }, + { + "name": "topo_test_canonical_frame", + "upstream_ref": "tests/prog_test/src/smTopoTest.cpp:368", + "inputs": { + "make": { + "kind": "canonical", + "o": [ + 1, + 2, + 3 + ], + "x": [ + 0, + 1, + 0 + ], + "y": [ + 0, + 0, + 1 + ] + }, + "ops": [ + { + "op": "state" + }, + { + "op": "toggle" + }, + { + "op": "state" + }, + { + "op": "rebuild" + }, + { + "op": "state" + }, + { + "op": "swap" + }, + { + "op": "state" + }, + { + "op": "reverse", + "v_dir": true + }, + { + "op": "state" + } + ] + } + }, + { + "name": "edge_degenerate_domain", + "upstream_ref": "edge case: zero-width domain", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 0 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 1, + 0, + 1, + 2 + ] + }, + "ops": [ + { + "op": "make_nurb" + }, + { + "op": "inherited", + "v": [ + 0, + 0, + 1 + ] + }, + { + "op": "eval_point", + "uv": [ + 3, + 3 + ] + }, + { + "op": "evaluate", + "uv": [ + 3, + 3 + ], + "hu": 1, + "hv": 1 + } + ] + } + }, + { + "name": "edge_nonperpendicular_axes", + "upstream_ref": "edge case: axes made perpendicular", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 1, + 1, + 1 + ], + "x": [ + 2, + 0, + 0 + ], + "y": [ + 1, + 1, + 0 + ], + "scale": [ + 0.5, + 3 + ], + "domain": [ + -1, + -1, + 1, + 1 + ] + }, + "ops": [ + { + "op": "state" + }, + { + "op": "eval_fast", + "uv": [ + 2, + -3 + ] + }, + { + "op": "project", + "p": [ + 0, + 4, + 9 + ] + }, + { + "op": "inherited", + "v": [ + 0, + 0, + 1 + ] + } + ] + } + }, + { + "name": "edge_reparameterize_keeps_origin", + "upstream_ref": "edge case: Reparameterize keeps the origin", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 0 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 2, + 3 + ], + "domain": [ + 1, + 1, + 2, + 3 + ] + }, + "ops": [ + { + "op": "reparam", + "dom": { + "explicit": [ + 0, + 0, + 1, + 1 + ] + } + }, + { + "op": "eval_point", + "uv": [ + 0, + 0 + ] + }, + { + "op": "eval_point", + "uv": [ + 1, + 1 + ] + }, + { + "op": "state" + } + ] + } + }, + { + "name": "edge_line_in_plane_point", + "upstream_ref": "edge case: line in the plane touching a corner (one parameter)", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 0 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 1, + 1 + ] + }, + "ops": [ + { + "op": "line", + "dom": "step", + "p": [ + 1, + 1, + 0 + ], + "v": [ + 1, + -1, + 0 + ], + "tol": 1e-06 + } + ] + } + }, + { + "name": "edge_drop_curve_bspline", + "upstream_ref": "edge case: B-spline drops inside and clamped outside", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + }, + "ops": [ + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "b_spline", + "dim": 3, + "p": 2, + "cpts": [ + [ + 1, + 1, + 2.1, + null + ], + [ + 3, + 5, + 1.9, + null + ], + [ + 6, + 2, + 2.3, + null + ], + [ + 8, + 8, + 2, + null + ] + ], + "knots": [ + 0, + 0, + 0, + 0.5, + 1, + 1, + 1 + ] + }, + "tol": 0.5 + }, + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "b_spline", + "dim": 3, + "p": 2, + "cpts": [ + [ + 1, + 1, + 2.1, + 1 + ], + [ + 3, + 5, + 1.9, + 2 + ], + [ + 6, + 2, + 2.3, + 1 + ], + [ + 8, + 8, + 2, + 1 + ] + ], + "knots": [ + 0, + 0, + 0, + 0.5, + 1, + 1, + 1 + ] + }, + "ivl": [ + 0.2, + 0.7 + ], + "tol": 0.5, + "keep_all": true + } + ] + } + }, + { + "name": "edge_drop_curve_bspline_fallback", + "upstream_ref": "edge case: B-spline drops inside and clamped outside (clamped control points: SmSurface::DropCurve)", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + }, + "ops": [ + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "b_spline", + "dim": 3, + "p": 2, + "cpts": [ + [ + 1, + 1, + 2.1, + null + ], + [ + 3, + 5, + 1.9, + null + ], + [ + 6, + 2, + 2.3, + null + ], + [ + 8, + 8, + 2, + null + ] + ], + "knots": [ + 0, + 0, + 0, + 0.5, + 1, + 1, + 1 + ] + }, + "tol": 0.001 + }, + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "b_spline", + "dim": 3, + "p": 2, + "cpts": [ + [ + 1, + 1, + 2, + null + ], + [ + 3, + 15, + 2, + null + ], + [ + 6, + 2, + 2, + null + ] + ], + "knots": [ + 0, + 0, + 0, + 1, + 1, + 1 + ] + }, + "tol": 0.001 + } + ] + } + }, + { + "name": "edge_drop_curve_perpendicular_line", + "upstream_ref": "edge case: a line perpendicular to the plane drops to a point", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + }, + "ops": [ + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "segment", + "a": [ + 3, + 3, + 0 + ], + "b": [ + 3, + 3, + 5 + ] + }, + "tol": 10, + "keep_all": true + }, + { + "op": "drop_curve", + "dom": "step", + "curve": { + "kind": "segment", + "a": [ + 30, + 3, + 2 + ], + "b": [ + 40, + 3, + 2 + ] + }, + "tol": 0.001, + "keep_all": true + } + ] + } + }, + { + "name": "edge_coincidence", + "upstream_ref": "edge case: plane/plane coincidence branches", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + }, + "ops": [ + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + } + }, + "tol": 1e-06, + "whole": true + }, + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 2, + 2, + 5, + 5 + ] + } + }, + "tol": 1e-06 + }, + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + -5, + -5, + 20, + 20 + ] + } + }, + "tol": 1e-06 + }, + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 12, + 0, + 20, + 10 + ] + } + }, + "tol": 1e-06 + }, + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 10, + 0, + 20, + 10 + ] + } + }, + "tol": 1e-06 + }, + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + -5, + 4, + 15, + 6 + ] + } + }, + "tol": 1e-06 + }, + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 0.7071067811865476, + 0.7071067811865476, + 0 + ], + "y": [ + -0.7071067811865476, + 0.7071067811865476, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + -3, + 12, + 3, + 14 + ] + } + }, + "tol": 1e-06 + }, + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2.5 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + } + }, + "tol": 1e-06 + }, + { + "op": "coincidence", + "other": { + "kind": "plane", + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0.01 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + } + }, + "tol": 1e-06, + "whole": true + } + ] + } + }, + { + "name": "edge_coincidence_bspline", + "upstream_ref": "edge case: plane/plane coincidence branches (not an SmPlane: SmSurface::IsPlanar)", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 2 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 10, + 10 + ] + }, + "ops": [ + { + "op": "coincidence", + "other": { + "kind": "b_spline", + "p": 1, + "q": 1, + "net": [ + [ + [ + 0, + 0, + 2, + null + ], + [ + 0, + 10, + 2, + null + ] + ], + [ + [ + 10, + 0, + 2, + null + ], + [ + 10, + 10, + 2, + null + ] + ] + ], + "u": [ + 0, + 0, + 1, + 1 + ], + "v": [ + 0, + 0, + 1, + 1 + ] + }, + "tol": 1e-06, + "whole": true + } + ] + } + }, + { + "name": "edge_trim_line", + "upstream_ref": "edge case: TrimPlaneLineToPlaneDomain", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 0 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 1, + 1 + ] + }, + "ops": [ + { + "op": "trim_line", + "dom": "step", + "a": [ + -1, + 0.5, + 0 + ], + "b": [ + 2, + 0.5, + 0 + ], + "tol": 0 + }, + { + "op": "trim_line", + "dom": "step", + "a": [ + 1, + 0.5, + 0 + ], + "b": [ + 2, + 0.5, + 0 + ], + "tol": 0 + }, + { + "op": "trim_line", + "dom": "step", + "a": [ + -1, + 0.5, + 0 + ], + "b": [ + 0, + 0.5, + 0 + ], + "tol": 0 + }, + { + "op": "trim_line", + "dom": "step", + "a": [ + 2, + 0.5, + 0 + ], + "b": [ + 3, + 0.5, + 0 + ], + "tol": 0 + }, + { + "op": "trim_line", + "dom": "step", + "a": [ + -1, + 2, + 0 + ], + "b": [ + 2, + 2, + 0 + ], + "tol": 0 + } + ] + } + }, + { + "name": "edge_grazing", + "upstream_ref": "edge case: sm_IsGrazingIntersection", + "inputs": { + "make": { + "kind": "bounded", + "o": [ + 0, + 0, + 0 + ], + "x": [ + 1, + 0, + 0 + ], + "y": [ + 0, + 1, + 0 + ], + "scale": [ + 1, + 1 + ], + "domain": [ + 0, + 0, + 1, + 1 + ] + }, + "ops": [ + { + "op": "grazing", + "curve": { + "kind": "b_spline", + "dim": 3, + "p": 2, + "cpts": [ + [ + 0, + 0, + 0, + null + ], + [ + 1, + 0, + 0, + null + ], + [ + 1, + 1, + 0, + null + ] + ], + "knots": [ + 0, + 0, + 0, + 1, + 1, + 1 + ] + }, + "t": 0, + "line": [ + [ + 0, + 0, + 0 + ], + [ + 2, + 0, + 0 + ] + ], + "s": 0 + }, + { + "op": "grazing", + "curve": { + "kind": "b_spline", + "dim": 3, + "p": 2, + "cpts": [ + [ + 0, + 0, + 0, + null + ], + [ + 1, + 0, + 0, + null + ], + [ + 2, + 0, + 0, + null + ] + ], + "knots": [ + 0, + 0, + 0, + 1, + 1, + 1 + ] + }, + "t": 0, + "line": [ + [ + 0, + 0, + 0 + ], + [ + 2, + 0, + 0 + ] + ], + "s": 0 + }, + { + "op": "grazing", + "curve": { + "kind": "segment", + "a": [ + 0, + 0, + 0 + ], + "b": [ + 1, + 1, + 0 + ] + }, + "t": 0.5, + "line": [ + [ + 0, + 0, + 0 + ], + [ + 2, + 0, + 0 + ] + ], + "s": 0 + } + ] + } + } + ] +} \ No newline at end of file diff --git a/harness/cpp/shim/surface_plane_p1.cpp b/harness/cpp/shim/surface_plane_p1.cpp new file mode 100644 index 0000000000..c45dfc5279 --- /dev/null +++ b/harness/cpp/shim/surface_plane_p1.cpp @@ -0,0 +1,838 @@ +// SPDX-License-Identifier: Apache-2.0 +// difftest shim for unit `surface.plane_p1`: the SmPlane members owned by the unit +// (source/SMLib/src/SmPlane.cpp, source/SMLib/inc/SmPlane.h), called on SmPlane objects (virtual +// dispatch is upstream's), plus the inherited SmBSplineSurface members the port re-dispatches for +// planes (GetNaturalUVDomain, GetMaxAnalyticDomain, IsBilinear, IsParallelToVector, GetDegree, +// GetNumberControlPoints, Reverse, SwapUV). +// +// One entry point, sc_surface_plane_p1_run(in, n_in, out, cap, out_len). `in` is a program: a +// plane block (plane A), the op count, then the ops; layouts are documented in +// crates/solidcore-ffi/src/units/surface_plane_p1.rs. Every read is bounds checked here (a bad +// program is SC_ERR_ARG). `out` receives `make_status`, then per op `op status [values]` (values +// only when the status is 0), then the state of A. A failed plane block ends the record after +// its status. +// +// Const queries that make the NURB of a plane without one (GetNaturalUVDomain and friends) are +// asked of a copy here, so that the record does not depend on when upstream makes it lazily; the +// state prints the NURB the plane has, or the one a copy makes. +#include "sc_shim.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace +{ +// Plane blocks (keep in sync with crates/solidcore-ffi/src/units/surface_plane_p1.rs). +enum : int32_t +{ + MK_BOUNDED = 0, + MK_NORMAL = 1, + MK_CANONICAL = 2, +}; + +// Ops (keep in sync with crates/solidcore-ffi/src/units/surface_plane_p1.rs). +enum : int32_t +{ + OP_STATE = 1, + OP_EVALUATE = 2, + OP_EVAL_POINT = 3, + OP_EVAL_FAST = 4, + OP_NORMAL = 5, + OP_PROJECT = 6, + OP_QUERIES = 7, + OP_KIND_OF = 8, + OP_ADJUST = 9, + OP_MAKE_NURB = 10, + OP_REPARAM = 11, + OP_TOGGLE = 12, + OP_REBUILD = 13, + OP_DROP = 14, + OP_LINE = 15, + OP_TRIM_LINE = 16, + OP_ISO = 17, + OP_DROP_CURVE = 18, + OP_COINCIDENCE = 19, + OP_EQ = 20, + OP_COPY = 21, + OP_GRAZING = 22, + OP_INHERITED = 23, + OP_REVERSE = 24, + OP_SWAP = 25, + OP_LAST = 25, +}; + +// Reads the protected STEP flags through pointers to members named in a derived class. +struct PeekS : SmBSplineSurface +{ + static SmKnotType SmBSplineSurface::*kt() { return &PeekS::m_eKnotType; } + static SmBSplineSurfaceForm SmBSplineSurface::*form() { return &PeekS::m_eBSplineSurfaceForm; } +}; + +struct PeekC : SmBSplineCurve +{ + static SmKnotType SmBSplineCurve::*kt() { return &PeekC::m_eKnotType; } + static SmBSplineCurveForm SmBSplineCurve::*form() { return &PeekC::m_eBSplineCurveForm; } +}; + +struct Bad : std::runtime_error +{ + Bad() : std::runtime_error("bad program") {} +}; + +struct Rd +{ + const double* in; + int64_t n; + int64_t at; + double num() + { + if (at >= n) + throw Bad(); + return in[at++]; + } + int64_t idx(int64_t lo, int64_t hi) + { + double d = num(); + if (!(d >= (double)lo && d <= (double)hi) || d != (double)(int64_t)d) + throw Bad(); + return (int64_t)d; + } + bool flag() { return idx(0, 1) != 0; } + SmVector3d vec() + { + double x = num(); + double y = num(); + double z = num(); + return SmVector3d(x, y, z); + } + SmPoint2d uv() + { + double x = num(); + double y = num(); + return SmPoint2d(x, y); + } + SmExtent2d dom4() + { + double a = num(); + double b = num(); + double c = num(); + double d = num(); + return SmExtent2d(a, b, c, d); + } +}; + +double st(SmStatus s) +{ + return s == SM_SUCCESS ? 0.0 : (double)s; +} + +double flg(SmBoolean b) +{ + return b ? 1.0 : 0.0; +} + +void put_vec(std::vector& o, const SmVector3d& v) +{ + o.push_back(v.x); + o.push_back(v.y); + o.push_back(v.z); +} + +void put_uv(std::vector& o, const SmPoint2d& v) +{ + o.push_back(v.x); + o.push_back(v.y); +} + +void put_dom(std::vector& o, const SmExtent2d& e) +{ + o.push_back(e.GetMin().x); + o.push_back(e.GetMin().y); + o.push_back(e.GetMax().x); + o.push_back(e.GetMax().y); +} + +void put_ivl(std::vector& o, const SmExtent1d& e) +{ + o.push_back(e.GetMin()); + o.push_back(e.GetMax()); +} + +void put_chars(std::vector& o, const TCHAR* s) +{ + for (; *s; s++) + o.push_back((double)(unsigned char)*s); +} + +// A plane block; NULL with *status set when the construction fails. +SmPlane* read_plane(Rd& rd, const SmContext& ctx, SmStatus* status) +{ + *status = SM_SUCCESS; + int64_t kind = rd.idx(0, 2); + switch (kind) + { + case MK_BOUNDED: + { + SmPoint3d o = rd.vec(); + SmVector3d x = rd.vec(); + SmVector3d y = rd.vec(); + SmVector2d s = rd.uv(); + SmExtent2d d = rd.dom4(); + return new (ctx) SmPlane(o, x, y, s, d, &ctx); + } + case MK_NORMAL: + { + SmPoint3d o = rd.vec(); + SmVector3d nv = rd.vec(); + return new (ctx) SmPlane(o, nv, &ctx); + } + default: + { + SmPoint3d o = rd.vec(); + SmVector3d x = rd.vec(); + SmVector3d y = rd.vec(); + SmAxis2Placement f(o, x, y); + SmPlane* p = NULL; + *status = SmPlane::CreateCanonical(ctx, f, p); + if (*status != SM_SUCCESS) + { + delete p; + return NULL; + } + return p; + } + } +} + +// `n m p q r s cpts(x y z w) u v` with sizes checked by the Rust side (1 <= p <= n <= 16). +SmBSplineSurface* read_bspline_surface(Rd& rd, const SmContext& ctx) +{ + gw_INDEX n = (gw_INDEX)rd.idx(1, 16); + gw_INDEX m = (gw_INDEX)rd.idx(1, 16); + gw_DEGREE p = (gw_DEGREE)rd.idx(1, 8); + gw_DEGREE q = (gw_DEGREE)rd.idx(1, 8); + gw_INDEX r = (gw_INDEX)rd.idx(3, 40); + gw_INDEX s = (gw_INDEX)rd.idx(3, 40); + if (p > n || q > m || r != n + p + 1 || s != m + q + 1) + throw Bad(); + std::vector v; + for (int64_t i = 0; i < 4 * (n + 1) * (m + 1) + r + 1 + s + 1; i++) + v.push_back(rd.num()); + gw_SURFACE* sur = sm_AllocateNurbSurface(n, m, p, q, r, s); + size_t k = 0; + for (gw_INDEX i = 0; i <= n; i++) + for (gw_INDEX j = 0; j <= m; j++) + { + sur->net->Pw[i][j].x = v[k++]; + sur->net->Pw[i][j].y = v[k++]; + sur->net->Pw[i][j].z = v[k++]; + sur->net->Pw[i][j].w = v[k++]; + } + for (gw_INDEX i = 0; i <= r; i++) + sur->knu->U[i] = v[k++]; + for (gw_INDEX i = 0; i <= s; i++) + sur->knv->U[i] = v[k++]; + return new (ctx) SmBSplineSurface(sur, FALSE, &ctx); +} + +// Another surface: `0 plane-block` or `1 bspline-surface`; NULL when the plane block fails. +SmSurface* read_surface(Rd& rd, const SmContext& ctx) +{ + int64_t kind = rd.idx(0, 1); + if (kind == 0) + { + SmStatus s = SM_SUCCESS; + SmPlane* p = read_plane(rd, ctx, &s); + if (p == NULL) + throw Bad(); + return p; + } + return read_bspline_surface(rd, ctx); +} + +// A curve: `0 a b` (CreateLineSegment, dim 3) or `1 dim n p m cpts(x y z w) knots`. +SmCurve* read_curve(Rd& rd, const SmContext& ctx) +{ + int64_t kind = rd.idx(0, 1); + if (kind == 0) + { + SmPoint3d a = rd.vec(); + SmPoint3d b = rd.vec(); + SmLine* l = NULL; + if (SmLine::CreateLineSegment(ctx, 3, a, b, l) != SM_SUCCESS || l == NULL) + throw Bad(); + return l; + } + ULONG dim = (ULONG)rd.idx(2, 3); + int64_t n = rd.idx(1, 32); + int64_t p = rd.idx(1, 8); + int64_t m = rd.idx(3, 64); + if (p > n || m != n + p + 1) + throw Bad(); + std::vector v; + for (int64_t i = 0; i < 4 * (n + 1) + m + 1; i++) + v.push_back(rd.num()); + gw_CURVE* cur = sm_AllocateNurbCurve((gw_INDEX)n, (gw_DEGREE)p, (gw_INDEX)m); + for (int64_t i = 0; i <= n; i++) + { + cur->pol->Pw[i].x = v[4 * i]; + cur->pol->Pw[i].y = v[4 * i + 1]; + cur->pol->Pw[i].z = v[4 * i + 2]; + cur->pol->Pw[i].w = v[4 * i + 3]; + } + for (int64_t i = 0; i <= m; i++) + cur->knt->U[i] = v[4 * (n + 1) + i]; + SmBSplineCurve* c = new (ctx) SmBSplineCurve(dim, (ULONG)cur->pol->n, (ULONG)cur->knt->m, (short)cur->p, + cur->pol->Pw, cur->knt->U, &ctx); + smos_Free(cur); + return c; +} + +void put_surface_nurb(std::vector& o, const gw_SURFACE* sur) +{ + o.push_back(sur ? 1.0 : 0.0); + if (!sur) + return; + gw_INDEX n = sur->net->n; + gw_INDEX m = sur->net->m; + gw_INDEX r = sur->knu->m; + gw_INDEX s = sur->knv->m; + o.push_back((double)n); + o.push_back((double)m); + o.push_back((double)sur->p); + o.push_back((double)sur->q); + o.push_back((double)r); + o.push_back((double)s); + for (gw_INDEX i = 0; i <= n; i++) + for (gw_INDEX j = 0; j <= m; j++) + { + o.push_back(sur->net->Pw[i][j].x); + o.push_back(sur->net->Pw[i][j].y); + o.push_back(sur->net->Pw[i][j].z); + o.push_back(sur->net->Pw[i][j].w); + } + for (gw_INDEX i = 0; i <= r; i++) + o.push_back(sur->knu->U[i]); + for (gw_INDEX i = 0; i <= s; i++) + o.push_back(sur->knv->U[i]); +} + +// A copy of `a` that leaves `a` alone: the copy constructor makes the source's missing NURB +// (through a const_cast), so a plane without NURB is rebuilt from its analytic data instead +// (SetCanonical keeps unit perpendicular axes as they are). +SmPlane* side_free_copy(const SmContext& ctx, const SmPlane* a) +{ + if (a->GetGwNurbPointer() != NULL) + return new (ctx) SmPlane(*a); + const SmAxis2Placement& pos = a->GetPosition(); + SmPlane* c = new (ctx) SmPlane(pos.GetOrigin(), pos.GetXAxis(), pos.GetYAxis(), a->GetUVScale(), + a->GetSTEPUVDomain(), &ctx); + c->GetOutOfBoundsEnabled() = a->IsOutOfBoundsEnabled(); + return c; +} + +// type O X Y Z domain scale oob kt form, then the NURB (made on a copy when missing). +void put_state(std::vector& o, const SmContext& ctx, const SmPlane* a) +{ + const SmAxis2Placement& pos = a->GetPosition(); + o.push_back((double)a->GetType()); + put_vec(o, pos.GetOrigin()); + put_vec(o, pos.GetXAxis()); + put_vec(o, pos.GetYAxis()); + put_vec(o, pos.GetZAxis()); + put_dom(o, a->GetSTEPUVDomain()); + SmVector2d sc = a->GetUVScale(); + put_uv(o, sc); + o.push_back(flg(a->IsOutOfBoundsEnabled())); + o.push_back((double)(a->*PeekS::kt())); + o.push_back((double)(a->*PeekS::form())); + const gw_SURFACE* sur = a->GetGwNurbPointer(); + if (sur) + { + put_surface_nurb(o, sur); + return; + } + SmPlane* tmp = side_free_copy(ctx, a); + put_surface_nurb(o, tmp->GetOrCreateGwNurbPointer()); + delete tmp; +} + +void put_curve_nurb(std::vector& o, const SmBSplineCurve* c) +{ + o.push_back((double)(c->*PeekC::kt())); + o.push_back((double)(c->*PeekC::form())); + const gw_CURVE* cur = c->GetGwNurbPointer(); + o.push_back(cur ? 1.0 : 0.0); + if (!cur) + return; + gw_INDEX n = cur->pol->n; + gw_INDEX m = cur->knt->m; + o.push_back((double)n); + o.push_back((double)cur->p); + o.push_back((double)m); + for (gw_INDEX i = 0; i <= n; i++) + { + o.push_back(cur->pol->Pw[i].x); + o.push_back(cur->pol->Pw[i].y); + o.push_back(cur->pol->Pw[i].z); + o.push_back(cur->pol->Pw[i].w); + } + for (gw_INDEX i = 0; i <= m; i++) + o.push_back(cur->knt->U[i]); +} + +// type dim [line: P V dom scale inside_out] B-spline part, natural interval. +void put_curve(std::vector& o, const SmCurve* c) +{ + o.push_back((double)c->GetType()); + o.push_back((double)c->GetDim()); + if (c->IsKindOf(SmLine_TYPE)) + { + const SmLine* l = (const SmLine*)c; + put_vec(o, l->GetLinePoint()); + put_vec(o, l->GetLineVector()); + put_ivl(o, l->GetSTEPInterval()); + o.push_back(l->GetLineScale()); + o.push_back(l->GetInsideOut() ? 1.0 : 0.0); + } + if (!c->IsKindOf(SmBSplineCurve_TYPE)) + throw Bad(); + put_curve_nurb(o, (const SmBSplineCurve*)c); + put_ivl(o, c->GetNaturalInterval()); +} + +double obj_id(const SmObject* p, const SmObject* a) +{ + if (p == NULL) + return -1.0; + return p == a ? 0.0 : 1.0; +} + +void put_sols(std::vector& o, SmSolutionArray& sols, const SmObject* a) +{ + o.push_back((double)sols.GetSize()); + for (ULONG i = 0; i < sols.GetSize(); i++) + { + const SmSolution& s = sols[i]; + o.push_back((double)s.m_eSolutionType); + o.push_back((double)s.m_lNumVariables); + o.push_back((double)s.m_lNumObjects); + o.push_back(s.m_lNumObjects > 0 ? obj_id(s.m_apObjects[0], a) : -1.0); + o.push_back(s.m_vStart.m_dSolutionValue); + for (ULONG k = 0; k < 3; k++) + o.push_back(k < s.m_lNumVariables ? s.m_vStart[k] : 0.0); + bool range = s.m_eSolutionType == SM_ST_RANGE_OF_VALUES; + o.push_back(range ? s.m_vEnd.m_dSolutionValue : 0.0); + for (ULONG k = 0; k < 3; k++) + o.push_back(range && k < s.m_lNumVariables ? s.m_vEnd[k] : 0.0); + } +} + +// Domain `kind a b c d`: 0 STEP domain, 1 SmExtent2d(a, b, c, d), 2 natural domain (of a copy). +SmExtent2d read_dom(Rd& rd, const SmContext& ctx, const SmPlane* a) +{ + int64_t kind = rd.idx(0, 2); + SmExtent2d d = rd.dom4(); + if (kind == 0) + return a->GetSTEPUVDomain(); + if (kind == 2) + { + SmPlane* tmp = side_free_copy(ctx, a); + SmExtent2d e = tmp->GetNaturalUVDomain(); + delete tmp; + return e; + } + return d; +} + +// The file-static sm_IsGrazingIntersection of SmPlane.cpp, copied verbatim (not exported). +SmBoolean is_grazing_intersection(const SmCurve* cpCurve, double dCurveParam, const SmLine* cpLine, + double dLineParam) +{ + SmVector3d sCurveEval[3]; + SmVector3d sLineEval[2]; + cpCurve->Evaluate(dCurveParam, 2, FALSE, sCurveEval); + cpLine->Evaluate(dLineParam, 1, FALSE, sLineEval); + if (!sCurveEval[1].IsParallelTo(sLineEval[1])) + { + return FALSE; + } + SmVector3d sCross(sCurveEval[1] * sCurveEval[2]); + if (sCross.LengthSquared() > SM_EFF_ZERO_SQ) + { + return TRUE; + } + return FALSE; +} + +void run_op(int32_t op, Rd& rd, const SmContext& ctx, SmPlane* a, std::vector& o) +{ + switch (op) + { + case OP_STATE: + o.push_back(0.0); + put_state(o, ctx, a); + break; + case OP_EVALUATE: + { + SmPoint2d uv = rd.uv(); + ULONG hu = (ULONG)rd.idx(0, 4); + ULONG hv = (ULONG)rd.idx(0, 4); + bool upper = rd.flag(); + if (upper && hu > hv) + throw Bad(); + std::vector d((hu + 1) * (hv + 1)); + for (size_t i = 0; i < d.size(); i++) + d[i].Set(0.0, 0.0, 0.0); + SmStatus s = a->Evaluate(uv, hu, hv, TRUE, TRUE, upper ? TRUE : FALSE, d.data()); + o.push_back(st(s)); + if (s == SM_SUCCESS) + for (size_t i = 0; i < d.size(); i++) + put_vec(o, d[i]); + break; + } + case OP_EVAL_POINT: + { + SmPoint2d uv = rd.uv(); + SmPoint3d p; + SmStatus s = a->EvaluatePoint(uv, p); + o.push_back(st(s)); + if (s == SM_SUCCESS) + put_vec(o, p); + break; + } + case OP_EVAL_FAST: + { + SmPoint2d uv = rd.uv(); + SmPoint3d p; + SmStatus s = a->EvaluatePointFast(uv, p); + o.push_back(st(s)); + if (s == SM_SUCCESS) + put_vec(o, p); + break; + } + case OP_NORMAL: + { + SmPoint2d uv = rd.uv(); + SmVector3d nv; + SmStatus s = a->EvaluateNormal(uv, TRUE, TRUE, nv); + o.push_back(st(s)); + if (s == SM_SUCCESS) + put_vec(o, nv); + break; + } + case OP_PROJECT: + { + SmPoint3d p = rd.vec(); + SmPoint2d uv; + SmStatus s = a->ProjectPointToUVDomain(p, uv); + o.push_back(st(s)); + if (s == SM_SUCCESS) + put_uv(o, uv); + break; + } + case OP_QUERIES: + { + SmPoint2d uv = rd.uv(); + o.push_back(0.0); + o.push_back(flg(a->IsBounded())); + SmPoint3d pp; + SmVector3d pn; + double dev = -7.0; + o.push_back(flg(a->IsPlanar(SM_EFF_ZERO, &pp, &pn, &dev))); + put_vec(o, pp); + put_vec(o, pn); + o.push_back(dev); + SmSurfParamType sd = SM_SP_UNKNOWN; + SmTArray cross; + cross.Add(uv); + o.push_back(flg(a->IsOnSeam(uv, NULL, &sd, &cross))); + o.push_back((double)sd); + o.push_back((double)cross.GetSize()); + SmContinuityType ct = SM_CT_UNDEFINED; + o.push_back(flg(a->IsClosed(a->GetSTEPUVDomain(), SM_SP_U, NULL, &ct))); + o.push_back((double)ct); + SmSurfParamType d1 = SM_SP_UNKNOWN; + o.push_back(flg(a->IsSingularity(uv, d1))); + o.push_back((double)d1); + SmSurfParamType d2 = SM_SP_UNKNOWN; + o.push_back(flg(a->IsSingularity(uv, 0, NULL, d2))); + o.push_back((double)d2); + o.push_back((double)a->GetType()); + put_chars(o, a->GetTypeString()); + o.push_back(-1.0); + put_chars(o, a->GetClassString()); + break; + } + case OP_KIND_OF: + { + double t = (double)rd.idx(0, 100000); + o.push_back(0.0); + o.push_back(flg(a->IsKindOf((SM_TYPE)t))); + break; + } + case OP_ADJUST: + { + SmExtent2d d = read_dom(rd, ctx, a); + o.push_back(st(a->AdjustSTEPUVDomain(d))); + break; + } + case OP_MAKE_NURB: o.push_back(st(a->MakeNurb())); break; + case OP_REPARAM: + { + SmExtent2d d = read_dom(rd, ctx, a); + o.push_back(st(a->Reparameterize(d))); + break; + } + case OP_TOGGLE: + a->ToggleSwapUVBit(); + o.push_back(0.0); + break; + case OP_REBUILD: o.push_back(st(a->RebuildSTEPFromNURBParameters())); break; + case OP_DROP: + { + SmExtent2d d = read_dom(rd, ctx, a); + SmSolverOperationType sop = (SmSolverOperationType)rd.idx(0, 5); + SmPoint3d p = rd.vec(); + double tol = rd.num(); + bool has = rd.flag(); + double target = rd.num(); + SmSolutionArray sols; + SmStatus s = a->DropPointFast(d, sop, p, NULL, tol, has ? &target : NULL, SM_SR_ALL, sols); + o.push_back(st(s)); + if (s == SM_SUCCESS) + put_sols(o, sols, a); + break; + } + case OP_LINE: + { + SmExtent2d d = read_dom(rd, ctx, a); + SmPoint3d p = rd.vec(); + SmVector3d v = rd.vec(); + bool has = rd.flag(); + double i0 = rd.num(); + double i1 = rd.num(); + bool ray = rd.flag(); + double tol = rd.num(); + SmExtent1d ivl(i0, i1); + SmSolutionArray sols; + SmStatus s = a->GlobalLineIntersect(d, p, v, has ? &ivl : NULL, ray ? TRUE : FALSE, tol, sols); + o.push_back(st(s)); + if (s == SM_SUCCESS) + put_sols(o, sols, a); + break; + } + case OP_TRIM_LINE: + { + SmExtent2d d = read_dom(rd, ctx, a); + SmPoint3d p0 = rd.vec(); + SmPoint3d p1 = rd.vec(); + double tol = rd.num(); + SmPoint3d t0, t1; + SmBoolean found = FALSE; + SmStatus s = a->TrimPlaneLineToPlaneDomain(d, p0, p1, tol, t0, t1, found); + o.push_back(st(s)); + if (s == SM_SUCCESS) + { + o.push_back(flg(found)); + if (found) + { + put_vec(o, t0); + put_vec(o, t1); + } + } + break; + } + case OP_ISO: + { + SmSurfParamType param = rd.idx(0, 1) == 0 ? SM_SP_U : SM_SP_V; + double iso = rd.num(); + bool has = rd.flag(); + SmExtent2d d = rd.dom4(); + bool want = rd.flag(); + SmBSplineCurve* c = NULL; + SmCurve* uv = NULL; + double gap = -7.0; + SmStatus s = a->CreateIsoParametricCurve(ctx, param, iso, 0.0, c, has ? &d : NULL, &gap, want ? &uv : NULL); + o.push_back(st(s)); + if (s == SM_SUCCESS) + { + if (c == NULL) + throw Bad(); + put_curve(o, c); + o.push_back(gap); + o.push_back(uv ? 1.0 : 0.0); + if (uv) + put_curve(o, uv); + } + delete c; + delete uv; + break; + } + case OP_DROP_CURVE: + { + SmExtent2d d = read_dom(rd, ctx, a); + SmCurve* c = read_curve(rd, ctx); + bool given = rd.flag(); + double i0 = rd.num(); + double i1 = rd.num(); + double tol = rd.num(); + bool keep = rd.flag(); + bool creating = rd.flag(); + SmExtent1d ivl = given ? SmExtent1d(i0, i1) : c->GetNaturalInterval(); + double dmax = -7.0; + double ddev = -7.0; + SmTArray arr; + SmStatus s = a->DropCurve(ctx, d, *c, ivl, tol, dmax, ddev, arr, keep ? TRUE : FALSE, NULL, + creating ? TRUE : FALSE); + o.push_back(st(s)); + if (s == SM_SUCCESS) + { + o.push_back(dmax); + o.push_back(ddev); + o.push_back((double)arr.GetSize()); + for (ULONG i = 0; i < arr.GetSize(); i++) + put_curve(o, arr[i]); + } + for (ULONG i = 0; i < arr.GetSize(); i++) + delete arr[i]; + delete c; + break; + } + case OP_COINCIDENCE: + { + SmSurface* other = read_surface(rd, ctx); + double tol = rd.num(); + bool whole = rd.flag(); + SmBoolean coinc = UNSURE; + double dist = -7.0; + SmSurface* containing = NULL; + SmStatus s = a->CoincidenceCheck(*other, tol, coinc, dist, whole ? TRUE : FALSE, containing); + o.push_back(st(s)); + if (s == SM_SUCCESS) + { + o.push_back(flg(coinc)); + o.push_back(dist); + } + delete other; + break; + } + case OP_EQ: + { + SmStatus ms = SM_SUCCESS; + SmPlane* b = read_plane(rd, ctx, &ms); + if (b == NULL) + throw Bad(); + o.push_back(0.0); + o.push_back(flg(*a == *b)); + delete b; + break; + } + case OP_COPY: + { + SmPlane* c = NULL; + SmStatus s = a->Copy(ctx, c); + o.push_back(st(s)); + if (s == SM_SUCCESS) + put_state(o, ctx, c); + delete c; + break; + } + case OP_GRAZING: + { + SmCurve* c = read_curve(rd, ctx); + double cp = rd.num(); + SmPoint3d l0 = rd.vec(); + SmPoint3d l1 = rd.vec(); + double lp = rd.num(); + SmLine* l = NULL; + if (SmLine::CreateLineSegment(ctx, 3, l0, l1, l) != SM_SUCCESS || l == NULL) + throw Bad(); + o.push_back(0.0); + o.push_back(flg(is_grazing_intersection(c, cp, l, lp))); + delete l; + delete c; + break; + } + case OP_INHERITED: + { + SmVector3d v = rd.vec(); + SmPlane* tmp = side_free_copy(ctx, a); + o.push_back(0.0); + put_dom(o, tmp->GetNaturalUVDomain()); + put_dom(o, tmp->GetMaxAnalyticDomain()); + o.push_back(flg(tmp->IsBilinear())); + o.push_back(flg(tmp->IsParallelToVector(v))); + o.push_back((double)tmp->GetDegree(SM_SP_U)); + o.push_back((double)tmp->GetDegree(SM_SP_V)); + o.push_back((double)tmp->GetNumberControlPoints(SM_SP_U)); + o.push_back((double)tmp->GetNumberControlPoints(SM_SP_V)); + delete tmp; + break; + } + case OP_REVERSE: + { + SmSurfParamType param = rd.idx(0, 1) == 0 ? SM_SP_U : SM_SP_V; + o.push_back(st(a->Reverse(param))); + break; + } + case OP_SWAP: o.push_back(st(a->SwapUV())); break; + default: throw Bad(); + } +} +} // namespace + +SC_EXPORT int32_t sc_surface_plane_p1_run(const double* in, int64_t n_in, double* out, int64_t cap, + int64_t* out_len) +{ + if (in == NULL || n_in < 2) + return SC_ERR_ARG; + try + { + SmContext ctx; + std::vector o; + Rd rd{in, n_in, 0}; + SmStatus ms = SM_SUCCESS; + SmPlane* a = read_plane(rd, ctx, &ms); + o.push_back(st(ms)); + if (a != NULL) + { + int64_t n_ops = rd.idx(0, 64); + for (int64_t i = 0; i < n_ops; i++) + { + int32_t op = (int32_t)rd.idx(1, OP_LAST); + o.push_back((double)op); + run_op(op, rd, ctx, a, o); + } + put_state(o, ctx, a); + delete a; + } + return sc_copy_out(o.data(), (int64_t)o.size(), out, cap, out_len); + } + catch (const Bad&) + { + return SC_ERR_ARG; + } + catch (...) + { + return SC_ERR_EXCEPTION; + } +} diff --git a/plan/findings.md b/plan/findings.md index 7d70cac611..8559370401 100644 --- a/plan/findings.md +++ b/plan/findings.md @@ -2539,3 +2539,38 @@ fixtures use Surface.sms and offset_nurb.sms from the allowed upstream corpus. The C++ shim deliberately excludes classifying a surface without a face: upstream would dereference null. FFI regression tests reject this path, truncated/trailing records, invalid counts and non-finite coordinates before entering C++. + +## surface.plane_p1 (`SmPlane`, part 1) + +All non-deferred cases agree bit for bit with upstream (`max_rel_err = 0`). Upstream +behaviour worth knowing: + +- **`SmPlane::Reparameterize` keeps the origin.** The new origin (`sOriginMax`) is only + computed inside `SM_DEBUG_CODE`. The release build changes the analytic domain and the + scales but keeps `m_vPosition`, so the analytic plane no longer matches its NURB unless + the new domain starts where the old one did. The port keeps this (fixture + `edge_reparameterize_keeps_origin`). +- **Lazy NURB through `const_cast`.** An `SmPlane` built by its constructors has no NURB. + `const` methods that need it (`GetNaturalUVDomain`, so `CoincidenceCheck`, + `CreateIsoParametricCurve`, `DropPointFast(SM_SO_NORMALIZE)` via `SmTol::MapTo2d`) make + it on `this` through `GetOrCreateGwNurbPointer`. So does the `SmBSplineSurface` copy + constructor, on the *source*. The port makes it on a copy (`Plane::base_with_nurb`), so + the source keeps none. Only `ToggleSwapUVBit` (which leaves the NURB alone) and + `operator==` (which compares NURBs) can see the difference. The runner generates those + two only while both sides agree. The shim copies planes without a NURB by rebuilding + them from their analytic data, because its own copies would otherwise change plane A. +- **`SmPlane::Evaluate` with `bOnlyUpperHalf` and more u than v derivatives** writes + outside its array (the `ULONG` index `lHighestVDeriv - k` wraps). The port returns + `InvalidInput`, and the ffi wrapper rejects that input. +- **Deferred paths:** `CoincidenceCheck` with a surface that is not an `SmPlane` needs + `SmSurface::IsPlanar` (`surface.surface_p7`), then `CreateNaturalUVTrimCurves` + (`surface.surface_p6`) and `DropPoint` (`surface.surface_p5`). `DropCurve` with a curve + whose control points must be clamped to the domain, or with a curve that is neither a + line nor a B-spline kind, needs the general `SmSurface::DropCurve` + (`intersect.surface_drop_lib_p3`). `GlobalLineIntersect` of a line lying in the plane + that meets the domain at a single line parameter needs the general + `SmSurface::GlobalLineIntersect` through the surface cache (`surface.surface_p8`). +- **`SmSurfaceCache` and planes.** The surface cache port treats its surface as a plain + B-spline. For an `SmPlane` it returns `SolidError::Unsupported` + (`CreateIsoParametricCurve`, which makes an `SmLine`, and the plane branch of + `CalculateBoundingBox`), or refuses the B-spline cast. diff --git a/plan/modules.toml b/plan/modules.toml index 1c7a62d707..c0a87655d1 100644 --- a/plan/modules.toml +++ b/plan/modules.toml @@ -1453,10 +1453,10 @@ depends_on = ["curve.curve_p2", "curve.curve_p4", "curve.curve_p5", "curve.curve est_lines = 1934 layer = 23 tests = ["prog_test:my_test_extent3d", "prog_test:my_test_vector2d", "prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_point", "prog_test:my_test_matrix", "prog_test:my_test_reversed_line_join"] -status = "todo" +status = "partial" claimed_by = "" claimed_at = "" -notes = "39 fns; largest: SmPlane::CoincidenceCheck, SmPlane::DropCurve, SmPlane::GlobalLineIntersect, SmPlane::DropPointFast; cycle back-edges (call into later units; stub or co-port): surface.surface_p1(2), surface.surface_p7(2), intersect.surface_drop_lib_p3(1), surface.surface_p5(1), surface.surface_p6(1), surface.surface_p8(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit" +notes = "partial: difftest 1518 cases (1391 passed, 127 deferred: intersect.surface_drop_lib_p3 83, surface.surface_p7 42, surface.surface_p8 2), max_rel_err 0; 39 fns; largest: SmPlane::CoincidenceCheck, SmPlane::DropCurve, SmPlane::GlobalLineIntersect, SmPlane::DropPointFast; cycle back-edges (call into later units; stub or co-port): surface.surface_p1(2), surface.surface_p7(2), intersect.surface_drop_lib_p3(1), surface.surface_p5(1), surface.surface_p6(1), surface.surface_p8(1); unit-SCC #22 (220 units); 319 upstream test entry points reach this unit" [[unit]] id = "surface.surf_of_revolution_p1" diff --git a/reports/difftest/surface.plane_p1.json b/reports/difftest/surface.plane_p1.json new file mode 100644 index 0000000000..a82eae5e7e --- /dev/null +++ b/reports/difftest/surface.plane_p1.json @@ -0,0 +1,12673 @@ +{ + "abs_floors": [], + "cases": [ + { + "max_rel_err": 0.0, + "name": "section_plane_adjust", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#0 (upstream tests/prog_test/src/smSurfaceTest.cpp:716)", + "values_compared": 253 + }, + { + "max_rel_err": 0.0, + "name": "curve_test_plane", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#1 (upstream tests/prog_test/src/smCurveTest.cpp:7296)", + "values_compared": 378 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "curve_test_plane_creating_fallback", + "outcome": "deferred", + "pass": false, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#2 (upstream tests/prog_test/src/smCurveTest.cpp:7296 (falls back to SmSurface::DropCurve))", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "merge_test_canonical", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#3 (upstream tests/prog_test/src/smMergeTest.cpp:605)", + "values_compared": 227 + }, + { + "max_rel_err": 0.0, + "name": "general_xy_plane", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#4 (upstream tests/SM_API_test/src/TestSmGeneral.cpp:1537)", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "error_codes_unit_square", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#5 (upstream tests/SM_API_test/src/TestSmErrorCodes.cpp:89)", + "values_compared": 164 + }, + { + "max_rel_err": 0.0, + "name": "topo_test_canonical_frame", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#6 (upstream tests/prog_test/src/smTopoTest.cpp:368)", + "values_compared": 337 + }, + { + "max_rel_err": 0.0, + "name": "edge_degenerate_domain", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#7 (upstream edge case: zero-width domain)", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "edge_nonperpendicular_axes", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#8 (upstream edge case: axes made perpendicular)", + "values_compared": 134 + }, + { + "max_rel_err": 0.0, + "name": "edge_reparameterize_keeps_origin", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#9 (upstream edge case: Reparameterize keeps the origin)", + "values_compared": 121 + }, + { + "deferred": { + "symbol": "SmSurface::GlobalLineIntersect", + "unit": "surface.surface_p8" + }, + "max_rel_err": 0.0, + "name": "edge_line_in_plane_point", + "outcome": "deferred", + "pass": false, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#10 (upstream edge case: line in the plane touching a corner (one parameter))", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "edge_drop_curve_bspline", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#11 (upstream edge case: B-spline drops inside and clamped outside)", + "values_compared": 130 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "edge_drop_curve_bspline_fallback", + "outcome": "deferred", + "pass": false, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#12 (upstream edge case: B-spline drops inside and clamped outside (clamped control points: SmSurface::DropCurve))", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "edge_drop_curve_perpendicular_line", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#13 (upstream edge case: a line perpendicular to the plane drops to a point)", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "edge_coincidence", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#14 (upstream edge case: plane/plane coincidence branches)", + "values_compared": 90 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "edge_coincidence_bspline", + "outcome": "deferred", + "pass": false, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#15 (upstream edge case: plane/plane coincidence branches (not an SmPlane: SmSurface::IsPlanar))", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "edge_trim_line", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#16 (upstream edge case: TrimPlaneLineToPlaneDomain)", + "values_compared": 87 + }, + { + "max_rel_err": 0.0, + "name": "edge_grazing", + "outcome": "pass", + "pass": true, + "source": "fixture:fixtures/surface.plane_p1/upstream.json#17 (upstream edge case: sm_IsGrazingIntersection)", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0000", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093610", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen0001", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093611", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0002", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093612", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0003", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093613", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0004", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093614", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0005", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093615", + "values_compared": 133 + }, + { + "max_rel_err": 0.0, + "name": "gen0006", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093616", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0007", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093617", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0008", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093618", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0009", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093619", + "values_compared": 127 + }, + { + "max_rel_err": 0.0, + "name": "gen0010", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093620", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0011", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093621", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0012", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093622", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0013", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093623", + "values_compared": 129 + }, + { + "max_rel_err": 0.0, + "name": "gen0014", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093624", + "values_compared": 168 + }, + { + "max_rel_err": 0.0, + "name": "gen0015", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093625", + "values_compared": 140 + }, + { + "max_rel_err": 0.0, + "name": "gen0016", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093626", + "values_compared": 72 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0017", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093627", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0018", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093628", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0019", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093629", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0020", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093630", + "values_compared": 174 + }, + { + "max_rel_err": 0.0, + "name": "gen0021", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093631", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0022", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093632", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0023", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093633", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0024", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093634", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0025", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093635", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0026", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093636", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen0027", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093637", + "values_compared": 77 + }, + { + "max_rel_err": 0.0, + "name": "gen0028", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093638", + "values_compared": 164 + }, + { + "max_rel_err": 0.0, + "name": "gen0029", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093639", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0030", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093640", + "values_compared": 125 + }, + { + "max_rel_err": 0.0, + "name": "gen0031", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093641", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen0032", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093642", + "values_compared": 117 + }, + { + "max_rel_err": 0.0, + "name": "gen0033", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093643", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0034", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093644", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0035", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093645", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0036", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093646", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0037", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093647", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0038", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093648", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0039", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093649", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0040", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093650", + "values_compared": 157 + }, + { + "max_rel_err": 0.0, + "name": "gen0041", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093651", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen0042", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093652", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0043", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093653", + "values_compared": 151 + }, + { + "max_rel_err": 0.0, + "name": "gen0044", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093654", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0045", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093655", + "values_compared": 123 + }, + { + "max_rel_err": 0.0, + "name": "gen0046", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093656", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0047", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093657", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0048", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093658", + "values_compared": 156 + }, + { + "max_rel_err": 0.0, + "name": "gen0049", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093659", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0050", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093660", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0051", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093661", + "values_compared": 128 + }, + { + "max_rel_err": 0.0, + "name": "gen0052", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093662", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0053", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093663", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen0054", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093664", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0055", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093665", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen0056", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093666", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0057", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093667", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0058", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093668", + "values_compared": 74 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0059", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093669", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0060", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093670", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen0061", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093671", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen0062", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093672", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0063", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093673", + "values_compared": 90 + }, + { + "max_rel_err": 0.0, + "name": "gen0064", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093674", + "values_compared": 144 + }, + { + "max_rel_err": 0.0, + "name": "gen0065", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093675", + "values_compared": 82 + }, + { + "max_rel_err": 0.0, + "name": "gen0066", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093676", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0067", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093677", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0068", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093678", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0069", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093679", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0070", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093680", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0071", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093681", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0072", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093682", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen0073", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093683", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0074", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093684", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0075", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093685", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0076", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093686", + "values_compared": 83 + }, + { + "max_rel_err": 0.0, + "name": "gen0077", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093687", + "values_compared": 75 + }, + { + "max_rel_err": 0.0, + "name": "gen0078", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093688", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0079", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093689", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen0080", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093690", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0081", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093691", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen0082", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093692", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen0083", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093693", + "values_compared": 142 + }, + { + "max_rel_err": 0.0, + "name": "gen0084", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093694", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen0085", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093695", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0086", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093696", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0087", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093697", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen0088", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093698", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0089", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093699", + "values_compared": 65 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0090", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093700", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0091", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093701", + "values_compared": 183 + }, + { + "max_rel_err": 0.0, + "name": "gen0092", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093702", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0093", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093703", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen0094", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093704", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0095", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093705", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen0096", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093706", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0097", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093707", + "values_compared": 58 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0098", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093708", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0099", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093709", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen0100", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093710", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0101", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093711", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0102", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093712", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0103", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093713", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0104", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093714", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen0105", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093715", + "values_compared": 162 + }, + { + "max_rel_err": 0.0, + "name": "gen0106", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093716", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0107", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093717", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0108", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093718", + "values_compared": 110 + }, + { + "max_rel_err": 0.0, + "name": "gen0109", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093719", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0110", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093720", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen0111", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093721", + "values_compared": 108 + }, + { + "max_rel_err": 0.0, + "name": "gen0112", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093722", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0113", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093723", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0114", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093724", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0115", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093725", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0116", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093726", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0117", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093727", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0118", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093728", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0119", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093729", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0120", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093730", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen0121", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093731", + "values_compared": 107 + }, + { + "max_rel_err": 0.0, + "name": "gen0122", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093732", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen0123", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093733", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0124", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093734", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0125", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093735", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen0126", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093736", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen0127", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093737", + "values_compared": 116 + }, + { + "max_rel_err": 0.0, + "name": "gen0128", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093738", + "values_compared": 110 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0129", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093739", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0130", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093740", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0131", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093741", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0132", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093742", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0133", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093743", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0134", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093744", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0135", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093745", + "values_compared": 88 + }, + { + "max_rel_err": 0.0, + "name": "gen0136", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093746", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0137", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093747", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0138", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093748", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0139", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093749", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0140", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093750", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen0141", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093751", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen0142", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093752", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0143", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093753", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0144", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093754", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0145", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093755", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0146", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093756", + "values_compared": 98 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0147", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093757", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0148", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093758", + "values_compared": 110 + }, + { + "max_rel_err": 0.0, + "name": "gen0149", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093759", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0150", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093760", + "values_compared": 152 + }, + { + "max_rel_err": 0.0, + "name": "gen0151", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093761", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen0152", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093762", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0153", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093763", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0154", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093764", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen0155", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093765", + "values_compared": 76 + }, + { + "max_rel_err": 0.0, + "name": "gen0156", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093766", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen0157", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093767", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0158", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093768", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0159", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093769", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen0160", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093770", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0161", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093771", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen0162", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093772", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0163", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093773", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen0164", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093774", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0165", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093775", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0166", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093776", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen0167", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093777", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen0168", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093778", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0169", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093779", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0170", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093780", + "values_compared": 165 + }, + { + "max_rel_err": 0.0, + "name": "gen0171", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093781", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0172", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093782", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0173", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093783", + "values_compared": 136 + }, + { + "max_rel_err": 0.0, + "name": "gen0174", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093784", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen0175", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093785", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0176", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093786", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0177", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093787", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0178", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093788", + "values_compared": 56 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0179", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093789", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0180", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093790", + "values_compared": 89 + }, + { + "max_rel_err": 0.0, + "name": "gen0181", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093791", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0182", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093792", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0183", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093793", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0184", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093794", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0185", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093795", + "values_compared": 133 + }, + { + "max_rel_err": 0.0, + "name": "gen0186", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093796", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0187", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093797", + "values_compared": 118 + }, + { + "max_rel_err": 0.0, + "name": "gen0188", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093798", + "values_compared": 76 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0189", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093799", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0190", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093800", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen0191", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093801", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0192", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093802", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen0193", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093803", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0194", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093804", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen0195", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093805", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0196", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093806", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0197", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093807", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0198", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093808", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen0199", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093809", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0200", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093810", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0201", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093811", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0202", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093812", + "values_compared": 87 + }, + { + "max_rel_err": 0.0, + "name": "gen0203", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093813", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0204", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093814", + "values_compared": 75 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0205", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093815", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0206", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093816", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen0207", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093817", + "values_compared": 88 + }, + { + "max_rel_err": 0.0, + "name": "gen0208", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093818", + "values_compared": 115 + }, + { + "max_rel_err": 0.0, + "name": "gen0209", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093819", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0210", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093820", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen0211", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093821", + "values_compared": 75 + }, + { + "max_rel_err": 0.0, + "name": "gen0212", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093822", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0213", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093823", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0214", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093824", + "values_compared": 132 + }, + { + "max_rel_err": 0.0, + "name": "gen0215", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093825", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0216", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093826", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0217", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093827", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0218", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093828", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen0219", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093829", + "values_compared": 133 + }, + { + "max_rel_err": 0.0, + "name": "gen0220", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093830", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen0221", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093831", + "values_compared": 147 + }, + { + "max_rel_err": 0.0, + "name": "gen0222", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093832", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0223", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093833", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0224", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093834", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen0225", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093835", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0226", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093836", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0227", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093837", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0228", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093838", + "values_compared": 125 + }, + { + "max_rel_err": 0.0, + "name": "gen0229", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093839", + "values_compared": 144 + }, + { + "max_rel_err": 0.0, + "name": "gen0230", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093840", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen0231", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093841", + "values_compared": 128 + }, + { + "max_rel_err": 0.0, + "name": "gen0232", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093842", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0233", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093843", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0234", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093844", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0235", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093845", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0236", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093846", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0237", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093847", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0238", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093848", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0239", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093849", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0240", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093850", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen0241", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093851", + "values_compared": 140 + }, + { + "max_rel_err": 0.0, + "name": "gen0242", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093852", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0243", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093853", + "values_compared": 133 + }, + { + "max_rel_err": 0.0, + "name": "gen0244", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093854", + "values_compared": 199 + }, + { + "max_rel_err": 0.0, + "name": "gen0245", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093855", + "values_compared": 59 + }, + { + "deferred": { + "symbol": "SmSurface::GlobalLineIntersect", + "unit": "surface.surface_p8" + }, + "max_rel_err": 0.0, + "name": "gen0246", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093856", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0247", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093857", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0248", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093858", + "values_compared": 123 + }, + { + "max_rel_err": 0.0, + "name": "gen0249", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093859", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0250", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093860", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0251", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093861", + "values_compared": 62 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0252", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093862", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0253", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093863", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0254", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093864", + "values_compared": 75 + }, + { + "max_rel_err": 0.0, + "name": "gen0255", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093865", + "values_compared": 172 + }, + { + "max_rel_err": 0.0, + "name": "gen0256", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093866", + "values_compared": 133 + }, + { + "max_rel_err": 0.0, + "name": "gen0257", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093867", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0258", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093868", + "values_compared": 141 + }, + { + "max_rel_err": 0.0, + "name": "gen0259", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093869", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0260", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093870", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0261", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093871", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen0262", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093872", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0263", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093873", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen0264", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093874", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0265", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093875", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen0266", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093876", + "values_compared": 85 + }, + { + "max_rel_err": 0.0, + "name": "gen0267", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093877", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen0268", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093878", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen0269", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093879", + "values_compared": 177 + }, + { + "max_rel_err": 0.0, + "name": "gen0270", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093880", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0271", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093881", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0272", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093882", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0273", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093883", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0274", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093884", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0275", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093885", + "values_compared": 90 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0276", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093886", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0277", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093887", + "values_compared": 130 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0278", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093888", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0279", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093889", + "values_compared": 139 + }, + { + "max_rel_err": 0.0, + "name": "gen0280", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093890", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen0281", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093891", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0282", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093892", + "values_compared": 118 + }, + { + "max_rel_err": 0.0, + "name": "gen0283", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093893", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0284", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093894", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0285", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093895", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen0286", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093896", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen0287", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093897", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0288", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093898", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0289", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093899", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0290", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093900", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen0291", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093901", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0292", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093902", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0293", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093903", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0294", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093904", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0295", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093905", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0296", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093906", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0297", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093907", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0298", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093908", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0299", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093909", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0300", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093910", + "values_compared": 169 + }, + { + "max_rel_err": 0.0, + "name": "gen0301", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093911", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0302", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093912", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0303", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093913", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0304", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093914", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0305", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093915", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0306", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093916", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0307", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093917", + "values_compared": 145 + }, + { + "max_rel_err": 0.0, + "name": "gen0308", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093918", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0309", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093919", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0310", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093920", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0311", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093921", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0312", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093922", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0313", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093923", + "values_compared": 60 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0314", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093924", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0315", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093925", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen0316", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093926", + "values_compared": 98 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0317", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093927", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0318", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093928", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0319", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093929", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0320", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093930", + "values_compared": 139 + }, + { + "max_rel_err": 0.0, + "name": "gen0321", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093931", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0322", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093932", + "values_compared": 147 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0323", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093933", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0324", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093934", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0325", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093935", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0326", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093936", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0327", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093937", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0328", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093938", + "values_compared": 139 + }, + { + "max_rel_err": 0.0, + "name": "gen0329", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093939", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen0330", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093940", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0331", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093941", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen0332", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093942", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0333", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093943", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0334", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093944", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0335", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093945", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0336", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093946", + "values_compared": 139 + }, + { + "max_rel_err": 0.0, + "name": "gen0337", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093947", + "values_compared": 85 + }, + { + "max_rel_err": 0.0, + "name": "gen0338", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093948", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen0339", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093949", + "values_compared": 137 + }, + { + "max_rel_err": 0.0, + "name": "gen0340", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093950", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0341", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093951", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0342", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093952", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0343", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093953", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0344", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093954", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0345", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093955", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0346", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093956", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0347", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093957", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0348", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093958", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0349", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093959", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen0350", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093960", + "values_compared": 187 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0351", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093961", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0352", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093962", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen0353", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093963", + "values_compared": 154 + }, + { + "max_rel_err": 0.0, + "name": "gen0354", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093964", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0355", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093965", + "values_compared": 89 + }, + { + "max_rel_err": 0.0, + "name": "gen0356", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093966", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0357", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093967", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0358", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093968", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0359", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093969", + "values_compared": 70 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0360", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093970", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0361", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093971", + "values_compared": 146 + }, + { + "max_rel_err": 0.0, + "name": "gen0362", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093972", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0363", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093973", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0364", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093974", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen0365", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093975", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0366", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093976", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0367", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093977", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0368", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093978", + "values_compared": 98 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0369", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093979", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0370", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093980", + "values_compared": 108 + }, + { + "max_rel_err": 0.0, + "name": "gen0371", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093981", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0372", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093982", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0373", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093983", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0374", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093984", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0375", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093985", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen0376", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093986", + "values_compared": 59 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0377", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093987", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0378", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093988", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0379", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093989", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0380", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093990", + "values_compared": 115 + }, + { + "max_rel_err": 0.0, + "name": "gen0381", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093991", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen0382", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093992", + "values_compared": 71 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0383", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005093993", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0384", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093994", + "values_compared": 115 + }, + { + "max_rel_err": 0.0, + "name": "gen0385", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093995", + "values_compared": 135 + }, + { + "max_rel_err": 0.0, + "name": "gen0386", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093996", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0387", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093997", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen0388", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093998", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0389", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005093999", + "values_compared": 77 + }, + { + "max_rel_err": 0.0, + "name": "gen0390", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094000", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0391", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094001", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0392", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094002", + "values_compared": 149 + }, + { + "max_rel_err": 0.0, + "name": "gen0393", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094003", + "values_compared": 90 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0394", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094004", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0395", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094005", + "values_compared": 171 + }, + { + "max_rel_err": 0.0, + "name": "gen0396", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094006", + "values_compared": 116 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0397", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094007", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0398", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094008", + "values_compared": 149 + }, + { + "max_rel_err": 0.0, + "name": "gen0399", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094009", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0400", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094010", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0401", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094011", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0402", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094012", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0403", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094013", + "values_compared": 133 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0404", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094014", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0405", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094015", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0406", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094016", + "values_compared": 123 + }, + { + "max_rel_err": 0.0, + "name": "gen0407", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094017", + "values_compared": 169 + }, + { + "max_rel_err": 0.0, + "name": "gen0408", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094018", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0409", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094019", + "values_compared": 132 + }, + { + "max_rel_err": 0.0, + "name": "gen0410", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094020", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0411", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094021", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0412", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094022", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen0413", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094023", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0414", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094024", + "values_compared": 139 + }, + { + "max_rel_err": 0.0, + "name": "gen0415", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094025", + "values_compared": 194 + }, + { + "max_rel_err": 0.0, + "name": "gen0416", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094026", + "values_compared": 150 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0417", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094027", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0418", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094028", + "values_compared": 60 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0419", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094029", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0420", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094030", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen0421", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094031", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0422", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094032", + "values_compared": 85 + }, + { + "max_rel_err": 0.0, + "name": "gen0423", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094033", + "values_compared": 152 + }, + { + "max_rel_err": 0.0, + "name": "gen0424", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094034", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0425", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094035", + "values_compared": 107 + }, + { + "max_rel_err": 0.0, + "name": "gen0426", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094036", + "values_compared": 138 + }, + { + "max_rel_err": 0.0, + "name": "gen0427", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094037", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0428", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094038", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0429", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094039", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen0430", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094040", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0431", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094041", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0432", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094042", + "values_compared": 67 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0433", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094043", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0434", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094044", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen0435", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094045", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen0436", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094046", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0437", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094047", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0438", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094048", + "values_compared": 228 + }, + { + "max_rel_err": 0.0, + "name": "gen0439", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094049", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0440", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094050", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0441", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094051", + "values_compared": 89 + }, + { + "max_rel_err": 0.0, + "name": "gen0442", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094052", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0443", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094053", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen0444", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094054", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0445", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094055", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0446", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094056", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0447", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094057", + "values_compared": 76 + }, + { + "max_rel_err": 0.0, + "name": "gen0448", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094058", + "values_compared": 125 + }, + { + "max_rel_err": 0.0, + "name": "gen0449", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094059", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0450", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094060", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen0451", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094061", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen0452", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094062", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen0453", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094063", + "values_compared": 148 + }, + { + "max_rel_err": 0.0, + "name": "gen0454", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094064", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen0455", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094065", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0456", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094066", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0457", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094067", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen0458", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094068", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0459", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094069", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0460", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094070", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0461", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094071", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen0462", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094072", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen0463", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094073", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen0464", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094074", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0465", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094075", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen0466", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094076", + "values_compared": 102 + }, + { + "max_rel_err": 0.0, + "name": "gen0467", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094077", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0468", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094078", + "values_compared": 151 + }, + { + "max_rel_err": 0.0, + "name": "gen0469", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094079", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0470", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094080", + "values_compared": 103 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0471", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094081", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0472", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094082", + "values_compared": 117 + }, + { + "max_rel_err": 0.0, + "name": "gen0473", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094083", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0474", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094084", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen0475", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094085", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0476", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094086", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0477", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094087", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen0478", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094088", + "values_compared": 105 + }, + { + "max_rel_err": 0.0, + "name": "gen0479", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094089", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0480", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094090", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0481", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094091", + "values_compared": 56 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0482", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094092", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0483", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094093", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0484", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094094", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0485", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094095", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0486", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094096", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0487", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094097", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0488", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094098", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen0489", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094099", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0490", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094100", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0491", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094101", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0492", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094102", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0493", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094103", + "values_compared": 75 + }, + { + "max_rel_err": 0.0, + "name": "gen0494", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094104", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0495", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094105", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0496", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094106", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen0497", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094107", + "values_compared": 126 + }, + { + "max_rel_err": 0.0, + "name": "gen0498", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094108", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0499", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094109", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0500", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094110", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0501", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094111", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0502", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094112", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0503", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094113", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0504", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094114", + "values_compared": 75 + }, + { + "max_rel_err": 0.0, + "name": "gen0505", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094115", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen0506", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094116", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0507", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094117", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0508", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094118", + "values_compared": 207 + }, + { + "max_rel_err": 0.0, + "name": "gen0509", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094119", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0510", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094120", + "values_compared": 126 + }, + { + "max_rel_err": 0.0, + "name": "gen0511", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094121", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0512", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094122", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen0513", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094123", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0514", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094124", + "values_compared": 168 + }, + { + "max_rel_err": 0.0, + "name": "gen0515", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094125", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0516", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094126", + "values_compared": 120 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0517", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094127", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0518", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094128", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen0519", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094129", + "values_compared": 140 + }, + { + "max_rel_err": 0.0, + "name": "gen0520", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094130", + "values_compared": 163 + }, + { + "max_rel_err": 0.0, + "name": "gen0521", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094131", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0522", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094132", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen0523", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094133", + "values_compared": 107 + }, + { + "max_rel_err": 0.0, + "name": "gen0524", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094134", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0525", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094135", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0526", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094136", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen0527", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094137", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen0528", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094138", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0529", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094139", + "values_compared": 136 + }, + { + "max_rel_err": 0.0, + "name": "gen0530", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094140", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0531", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094141", + "values_compared": 140 + }, + { + "max_rel_err": 0.0, + "name": "gen0532", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094142", + "values_compared": 85 + }, + { + "max_rel_err": 0.0, + "name": "gen0533", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094143", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0534", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094144", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0535", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094145", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0536", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094146", + "values_compared": 65 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0537", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094147", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0538", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094148", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen0539", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094149", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0540", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094150", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen0541", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094151", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen0542", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094152", + "values_compared": 132 + }, + { + "max_rel_err": 0.0, + "name": "gen0543", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094153", + "values_compared": 228 + }, + { + "max_rel_err": 0.0, + "name": "gen0544", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094154", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen0545", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094155", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0546", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094156", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0547", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094157", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0548", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094158", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0549", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094159", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0550", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094160", + "values_compared": 115 + }, + { + "max_rel_err": 0.0, + "name": "gen0551", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094161", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen0552", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094162", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0553", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094163", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0554", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094164", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0555", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094165", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen0556", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094166", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0557", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094167", + "values_compared": 77 + }, + { + "max_rel_err": 0.0, + "name": "gen0558", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094168", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0559", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094169", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0560", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094170", + "values_compared": 127 + }, + { + "max_rel_err": 0.0, + "name": "gen0561", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094171", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0562", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094172", + "values_compared": 127 + }, + { + "max_rel_err": 0.0, + "name": "gen0563", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094173", + "values_compared": 85 + }, + { + "max_rel_err": 0.0, + "name": "gen0564", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094174", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0565", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094175", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0566", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094176", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen0567", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094177", + "values_compared": 71 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0568", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094178", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0569", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094179", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0570", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094180", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen0571", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094181", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0572", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094182", + "values_compared": 153 + }, + { + "max_rel_err": 0.0, + "name": "gen0573", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094183", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0574", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094184", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0575", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094185", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0576", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094186", + "values_compared": 82 + }, + { + "max_rel_err": 0.0, + "name": "gen0577", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094187", + "values_compared": 121 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0578", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094188", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0579", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094189", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0580", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094190", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen0581", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094191", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen0582", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094192", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen0583", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094193", + "values_compared": 57 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0584", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094194", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0585", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094195", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0586", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094196", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0587", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094197", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0588", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094198", + "values_compared": 105 + }, + { + "max_rel_err": 0.0, + "name": "gen0589", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094199", + "values_compared": 117 + }, + { + "max_rel_err": 0.0, + "name": "gen0590", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094200", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0591", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094201", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0592", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094202", + "values_compared": 197 + }, + { + "max_rel_err": 0.0, + "name": "gen0593", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094203", + "values_compared": 57 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0594", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094204", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0595", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094205", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0596", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094206", + "values_compared": 83 + }, + { + "max_rel_err": 0.0, + "name": "gen0597", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094207", + "values_compared": 90 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0598", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094208", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0599", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094209", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0600", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094210", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen0601", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094211", + "values_compared": 83 + }, + { + "max_rel_err": 0.0, + "name": "gen0602", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094212", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0603", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094213", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0604", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094214", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen0605", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094215", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0606", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094216", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0607", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094217", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0608", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094218", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0609", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094219", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0610", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094220", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0611", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094221", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0612", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094222", + "values_compared": 127 + }, + { + "max_rel_err": 0.0, + "name": "gen0613", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094223", + "values_compared": 63 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0614", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094224", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0615", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094225", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0616", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094226", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0617", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094227", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0618", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094228", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0619", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094229", + "values_compared": 166 + }, + { + "max_rel_err": 0.0, + "name": "gen0620", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094230", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0621", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094231", + "values_compared": 151 + }, + { + "max_rel_err": 0.0, + "name": "gen0622", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094232", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0623", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094233", + "values_compared": 90 + }, + { + "max_rel_err": 0.0, + "name": "gen0624", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094234", + "values_compared": 156 + }, + { + "max_rel_err": 0.0, + "name": "gen0625", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094235", + "values_compared": 106 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0626", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094236", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0627", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094237", + "values_compared": 155 + }, + { + "max_rel_err": 0.0, + "name": "gen0628", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094238", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0629", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094239", + "values_compared": 140 + }, + { + "max_rel_err": 0.0, + "name": "gen0630", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094240", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0631", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094241", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen0632", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094242", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen0633", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094243", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0634", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094244", + "values_compared": 115 + }, + { + "max_rel_err": 0.0, + "name": "gen0635", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094245", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0636", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094246", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0637", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094247", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0638", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094248", + "values_compared": 90 + }, + { + "max_rel_err": 0.0, + "name": "gen0639", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094249", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0640", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094250", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0641", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094251", + "values_compared": 155 + }, + { + "max_rel_err": 0.0, + "name": "gen0642", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094252", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen0643", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094253", + "values_compared": 166 + }, + { + "max_rel_err": 0.0, + "name": "gen0644", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094254", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen0645", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094255", + "values_compared": 179 + }, + { + "max_rel_err": 0.0, + "name": "gen0646", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094256", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0647", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094257", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen0648", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094258", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen0649", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094259", + "values_compared": 141 + }, + { + "max_rel_err": 0.0, + "name": "gen0650", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094260", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0651", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094261", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0652", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094262", + "values_compared": 201 + }, + { + "max_rel_err": 0.0, + "name": "gen0653", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094263", + "values_compared": 144 + }, + { + "max_rel_err": 0.0, + "name": "gen0654", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094264", + "values_compared": 159 + }, + { + "max_rel_err": 0.0, + "name": "gen0655", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094265", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen0656", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094266", + "values_compared": 136 + }, + { + "max_rel_err": 0.0, + "name": "gen0657", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094267", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen0658", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094268", + "values_compared": 154 + }, + { + "max_rel_err": 0.0, + "name": "gen0659", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094269", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0660", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094270", + "values_compared": 136 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0661", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094271", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0662", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094272", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0663", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094273", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0664", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094274", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0665", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094275", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0666", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094276", + "values_compared": 123 + }, + { + "max_rel_err": 0.0, + "name": "gen0667", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094277", + "values_compared": 107 + }, + { + "max_rel_err": 0.0, + "name": "gen0668", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094278", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen0669", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094279", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0670", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094280", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0671", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094281", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0672", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094282", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0673", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094283", + "values_compared": 137 + }, + { + "max_rel_err": 0.0, + "name": "gen0674", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094284", + "values_compared": 153 + }, + { + "max_rel_err": 0.0, + "name": "gen0675", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094285", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0676", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094286", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0677", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094287", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0678", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094288", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0679", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094289", + "values_compared": 139 + }, + { + "max_rel_err": 0.0, + "name": "gen0680", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094290", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0681", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094291", + "values_compared": 71 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0682", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094292", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0683", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094293", + "values_compared": 148 + }, + { + "max_rel_err": 0.0, + "name": "gen0684", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094294", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0685", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094295", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0686", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094296", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0687", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094297", + "values_compared": 201 + }, + { + "max_rel_err": 0.0, + "name": "gen0688", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094298", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen0689", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094299", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0690", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094300", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0691", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094301", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0692", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094302", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0693", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094303", + "values_compared": 133 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0694", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094304", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0695", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094305", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0696", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094306", + "values_compared": 105 + }, + { + "max_rel_err": 0.0, + "name": "gen0697", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094307", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0698", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094308", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen0699", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094309", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0700", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094310", + "values_compared": 69 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0701", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094311", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0702", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094312", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen0703", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094313", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0704", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094314", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0705", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094315", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0706", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094316", + "values_compared": 107 + }, + { + "max_rel_err": 0.0, + "name": "gen0707", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094317", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0708", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094318", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0709", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094319", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0710", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094320", + "values_compared": 115 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0711", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094321", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0712", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094322", + "values_compared": 150 + }, + { + "max_rel_err": 0.0, + "name": "gen0713", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094323", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0714", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094324", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen0715", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094325", + "values_compared": 105 + }, + { + "max_rel_err": 0.0, + "name": "gen0716", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094326", + "values_compared": 116 + }, + { + "max_rel_err": 0.0, + "name": "gen0717", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094327", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen0718", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094328", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0719", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094329", + "values_compared": 108 + }, + { + "max_rel_err": 0.0, + "name": "gen0720", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094330", + "values_compared": 170 + }, + { + "max_rel_err": 0.0, + "name": "gen0721", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094331", + "values_compared": 61 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0722", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094332", + "values_compared": 0 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0723", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094333", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0724", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094334", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0725", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094335", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0726", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094336", + "values_compared": 142 + }, + { + "max_rel_err": 0.0, + "name": "gen0727", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094337", + "values_compared": 222 + }, + { + "max_rel_err": 0.0, + "name": "gen0728", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094338", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen0729", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094339", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0730", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094340", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0731", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094341", + "values_compared": 110 + }, + { + "max_rel_err": 0.0, + "name": "gen0732", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094342", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0733", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094343", + "values_compared": 71 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0734", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094344", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0735", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094345", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0736", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094346", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0737", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094347", + "values_compared": 178 + }, + { + "max_rel_err": 0.0, + "name": "gen0738", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094348", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0739", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094349", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0740", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094350", + "values_compared": 212 + }, + { + "max_rel_err": 0.0, + "name": "gen0741", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094351", + "values_compared": 125 + }, + { + "max_rel_err": 0.0, + "name": "gen0742", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094352", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen0743", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094353", + "values_compared": 107 + }, + { + "max_rel_err": 0.0, + "name": "gen0744", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094354", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0745", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094355", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0746", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094356", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0747", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094357", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen0748", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094358", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0749", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094359", + "values_compared": 171 + }, + { + "max_rel_err": 0.0, + "name": "gen0750", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094360", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0751", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094361", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0752", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094362", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0753", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094363", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0754", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094364", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen0755", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094365", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0756", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094366", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0757", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094367", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0758", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094368", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0759", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094369", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0760", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094370", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0761", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094371", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen0762", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094372", + "values_compared": 116 + }, + { + "max_rel_err": 0.0, + "name": "gen0763", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094373", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen0764", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094374", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0765", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094375", + "values_compared": 160 + }, + { + "max_rel_err": 0.0, + "name": "gen0766", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094376", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0767", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094377", + "values_compared": 123 + }, + { + "max_rel_err": 0.0, + "name": "gen0768", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094378", + "values_compared": 108 + }, + { + "max_rel_err": 0.0, + "name": "gen0769", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094379", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0770", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094380", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0771", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094381", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0772", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094382", + "values_compared": 69 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0773", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094383", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0774", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094384", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen0775", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094385", + "values_compared": 87 + }, + { + "max_rel_err": 0.0, + "name": "gen0776", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094386", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0777", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094387", + "values_compared": 175 + }, + { + "max_rel_err": 0.0, + "name": "gen0778", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094388", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen0779", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094389", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0780", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094390", + "values_compared": 88 + }, + { + "max_rel_err": 0.0, + "name": "gen0781", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094391", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen0782", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094392", + "values_compared": 105 + }, + { + "max_rel_err": 0.0, + "name": "gen0783", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094393", + "values_compared": 149 + }, + { + "max_rel_err": 0.0, + "name": "gen0784", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094394", + "values_compared": 108 + }, + { + "max_rel_err": 0.0, + "name": "gen0785", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094395", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0786", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094396", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0787", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094397", + "values_compared": 127 + }, + { + "max_rel_err": 0.0, + "name": "gen0788", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094398", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0789", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094399", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen0790", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094400", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0791", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094401", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen0792", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094402", + "values_compared": 150 + }, + { + "max_rel_err": 0.0, + "name": "gen0793", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094403", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen0794", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094404", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0795", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094405", + "values_compared": 56 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0796", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094406", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0797", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094407", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0798", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094408", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0799", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094409", + "values_compared": 63 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0800", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094410", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0801", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094411", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0802", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094412", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen0803", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094413", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0804", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094414", + "values_compared": 142 + }, + { + "max_rel_err": 0.0, + "name": "gen0805", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094415", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen0806", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094416", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0807", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094417", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0808", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094418", + "values_compared": 167 + }, + { + "max_rel_err": 0.0, + "name": "gen0809", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094419", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0810", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094420", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0811", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094421", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0812", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094422", + "values_compared": 116 + }, + { + "max_rel_err": 0.0, + "name": "gen0813", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094423", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0814", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094424", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0815", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094425", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen0816", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094426", + "values_compared": 154 + }, + { + "max_rel_err": 0.0, + "name": "gen0817", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094427", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen0818", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094428", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0819", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094429", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0820", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094430", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen0821", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094431", + "values_compared": 63 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0822", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094432", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0823", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094433", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen0824", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094434", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0825", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094435", + "values_compared": 66 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0826", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094436", + "values_compared": 0 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0827", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094437", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0828", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094438", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0829", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094439", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen0830", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094440", + "values_compared": 158 + }, + { + "max_rel_err": 0.0, + "name": "gen0831", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094441", + "values_compared": 146 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0832", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094442", + "values_compared": 0 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0833", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094443", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0834", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094444", + "values_compared": 90 + }, + { + "max_rel_err": 0.0, + "name": "gen0835", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094445", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0836", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094446", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0837", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094447", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0838", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094448", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen0839", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094449", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen0840", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094450", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0841", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094451", + "values_compared": 77 + }, + { + "max_rel_err": 0.0, + "name": "gen0842", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094452", + "values_compared": 161 + }, + { + "max_rel_err": 0.0, + "name": "gen0843", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094453", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen0844", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094454", + "values_compared": 142 + }, + { + "max_rel_err": 0.0, + "name": "gen0845", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094455", + "values_compared": 108 + }, + { + "max_rel_err": 0.0, + "name": "gen0846", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094456", + "values_compared": 59 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0847", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094457", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0848", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094458", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0849", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094459", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen0850", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094460", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen0851", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094461", + "values_compared": 149 + }, + { + "max_rel_err": 0.0, + "name": "gen0852", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094462", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0853", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094463", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0854", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094464", + "values_compared": 134 + }, + { + "max_rel_err": 0.0, + "name": "gen0855", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094465", + "values_compared": 76 + }, + { + "max_rel_err": 0.0, + "name": "gen0856", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094466", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0857", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094467", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0858", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094468", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen0859", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094469", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen0860", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094470", + "values_compared": 148 + }, + { + "max_rel_err": 0.0, + "name": "gen0861", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094471", + "values_compared": 108 + }, + { + "max_rel_err": 0.0, + "name": "gen0862", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094472", + "values_compared": 126 + }, + { + "max_rel_err": 0.0, + "name": "gen0863", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094473", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0864", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094474", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0865", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094475", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0866", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094476", + "values_compared": 57 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0867", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094477", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0868", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094478", + "values_compared": 189 + }, + { + "max_rel_err": 0.0, + "name": "gen0869", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094479", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0870", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094480", + "values_compared": 129 + }, + { + "max_rel_err": 0.0, + "name": "gen0871", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094481", + "values_compared": 137 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0872", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094482", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0873", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094483", + "values_compared": 171 + }, + { + "max_rel_err": 0.0, + "name": "gen0874", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094484", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0875", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094485", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0876", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094486", + "values_compared": 121 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0877", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094487", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0878", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094488", + "values_compared": 118 + }, + { + "max_rel_err": 0.0, + "name": "gen0879", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094489", + "values_compared": 128 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0880", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094490", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0881", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094491", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0882", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094492", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0883", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094493", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen0884", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094494", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0885", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094495", + "values_compared": 85 + }, + { + "max_rel_err": 0.0, + "name": "gen0886", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094496", + "values_compared": 102 + }, + { + "max_rel_err": 0.0, + "name": "gen0887", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094497", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen0888", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094498", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen0889", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094499", + "values_compared": 109 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0890", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094500", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0891", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094501", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen0892", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094502", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0893", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094503", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen0894", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094504", + "values_compared": 75 + }, + { + "max_rel_err": 0.0, + "name": "gen0895", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094505", + "values_compared": 170 + }, + { + "max_rel_err": 0.0, + "name": "gen0896", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094506", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0897", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094507", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0898", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094508", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0899", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094509", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen0900", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094510", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0901", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094511", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0902", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094512", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen0903", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094513", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen0904", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094514", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0905", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094515", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0906", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094516", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0907", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094517", + "values_compared": 155 + }, + { + "max_rel_err": 0.0, + "name": "gen0908", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094518", + "values_compared": 115 + }, + { + "max_rel_err": 0.0, + "name": "gen0909", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094519", + "values_compared": 92 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0910", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094520", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0911", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094521", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0912", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094522", + "values_compared": 135 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0913", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094523", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0914", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094524", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0915", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094525", + "values_compared": 77 + }, + { + "max_rel_err": 0.0, + "name": "gen0916", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094526", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0917", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094527", + "values_compared": 123 + }, + { + "max_rel_err": 0.0, + "name": "gen0918", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094528", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0919", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094529", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0920", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094530", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0921", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094531", + "values_compared": 142 + }, + { + "max_rel_err": 0.0, + "name": "gen0922", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094532", + "values_compared": 109 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0923", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094533", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0924", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094534", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0925", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094535", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0926", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094536", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0927", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094537", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen0928", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094538", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen0929", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094539", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen0930", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094540", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen0931", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094541", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen0932", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094542", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen0933", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094543", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen0934", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094544", + "values_compared": 127 + }, + { + "max_rel_err": 0.0, + "name": "gen0935", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094545", + "values_compared": 110 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0936", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094546", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0937", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094547", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0938", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094548", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen0939", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094549", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0940", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094550", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen0941", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094551", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0942", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094552", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0943", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094553", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen0944", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094554", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0945", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094555", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0946", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094556", + "values_compared": 134 + }, + { + "max_rel_err": 0.0, + "name": "gen0947", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094557", + "values_compared": 62 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0948", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094558", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0949", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094559", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0950", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094560", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen0951", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094561", + "values_compared": 82 + }, + { + "max_rel_err": 0.0, + "name": "gen0952", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094562", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen0953", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094563", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0954", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094564", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0955", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094565", + "values_compared": 110 + }, + { + "max_rel_err": 0.0, + "name": "gen0956", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094566", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen0957", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094567", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen0958", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094568", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen0959", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094569", + "values_compared": 61 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0960", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094570", + "values_compared": 0 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0961", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094571", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0962", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094572", + "values_compared": 57 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0963", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094573", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0964", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094574", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen0965", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094575", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen0966", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094576", + "values_compared": 61 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0967", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094577", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0968", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094578", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen0969", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094579", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen0970", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094580", + "values_compared": 90 + }, + { + "max_rel_err": 0.0, + "name": "gen0971", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094581", + "values_compared": 78 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0972", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094582", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0973", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094583", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen0974", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094584", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0975", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094585", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen0976", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094586", + "values_compared": 113 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen0977", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094587", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0978", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094588", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen0979", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094589", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen0980", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094590", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen0981", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094591", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen0982", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094592", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen0983", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094593", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen0984", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094594", + "values_compared": 70 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0985", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094595", + "values_compared": 0 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0986", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094596", + "values_compared": 0 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen0987", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094597", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen0988", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094598", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0989", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094599", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen0990", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094600", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen0991", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094601", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen0992", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094602", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen0993", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094603", + "values_compared": 127 + }, + { + "max_rel_err": 0.0, + "name": "gen0994", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094604", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen0995", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094605", + "values_compared": 190 + }, + { + "max_rel_err": 0.0, + "name": "gen0996", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094606", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen0997", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094607", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen0998", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094608", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen0999", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094609", + "values_compared": 168 + }, + { + "max_rel_err": 0.0, + "name": "gen1000", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094610", + "values_compared": 133 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1001", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094611", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1002", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094612", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen1003", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094613", + "values_compared": 100 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1004", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094614", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1005", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094615", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen1006", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094616", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen1007", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094617", + "values_compared": 145 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1008", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094618", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1009", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094619", + "values_compared": 57 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1010", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094620", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1011", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094621", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1012", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094622", + "values_compared": 131 + }, + { + "max_rel_err": 0.0, + "name": "gen1013", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094623", + "values_compared": 143 + }, + { + "max_rel_err": 0.0, + "name": "gen1014", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094624", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen1015", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094625", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen1016", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094626", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1017", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094627", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1018", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094628", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen1019", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094629", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen1020", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094630", + "values_compared": 61 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1021", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094631", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1022", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094632", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1023", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094633", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1024", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094634", + "values_compared": 146 + }, + { + "max_rel_err": 0.0, + "name": "gen1025", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094635", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen1026", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094636", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1027", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094637", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen1028", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094638", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1029", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094639", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1030", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094640", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1031", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094641", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1032", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094642", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen1033", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094643", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1034", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094644", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1035", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094645", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1036", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094646", + "values_compared": 139 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1037", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094647", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1038", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094648", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen1039", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094649", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen1040", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094650", + "values_compared": 139 + }, + { + "max_rel_err": 0.0, + "name": "gen1041", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094651", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1042", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094652", + "values_compared": 170 + }, + { + "max_rel_err": 0.0, + "name": "gen1043", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094653", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1044", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094654", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen1045", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094655", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen1046", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094656", + "values_compared": 194 + }, + { + "max_rel_err": 0.0, + "name": "gen1047", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094657", + "values_compared": 125 + }, + { + "max_rel_err": 0.0, + "name": "gen1048", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094658", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen1049", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094659", + "values_compared": 76 + }, + { + "max_rel_err": 0.0, + "name": "gen1050", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094660", + "values_compared": 150 + }, + { + "max_rel_err": 0.0, + "name": "gen1051", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094661", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen1052", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094662", + "values_compared": 224 + }, + { + "max_rel_err": 0.0, + "name": "gen1053", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094663", + "values_compared": 114 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1054", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094664", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1055", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094665", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1056", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094666", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen1057", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094667", + "values_compared": 136 + }, + { + "max_rel_err": 0.0, + "name": "gen1058", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094668", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen1059", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094669", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen1060", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094670", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen1061", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094671", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1062", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094672", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen1063", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094673", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1064", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094674", + "values_compared": 59 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1065", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094675", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1066", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094676", + "values_compared": 72 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1067", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094677", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1068", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094678", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen1069", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094679", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen1070", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094680", + "values_compared": 153 + }, + { + "max_rel_err": 0.0, + "name": "gen1071", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094681", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1072", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094682", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen1073", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094683", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1074", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094684", + "values_compared": 145 + }, + { + "max_rel_err": 0.0, + "name": "gen1075", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094685", + "values_compared": 170 + }, + { + "max_rel_err": 0.0, + "name": "gen1076", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094686", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1077", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094687", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen1078", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094688", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1079", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094689", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1080", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094690", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen1081", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094691", + "values_compared": 56 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1082", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094692", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1083", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094693", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen1084", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094694", + "values_compared": 126 + }, + { + "max_rel_err": 0.0, + "name": "gen1085", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094695", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1086", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094696", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen1087", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094697", + "values_compared": 160 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1088", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094698", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1089", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094699", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen1090", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094700", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1091", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094701", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen1092", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094702", + "values_compared": 118 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1093", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094703", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1094", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094704", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen1095", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094705", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1096", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094706", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1097", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094707", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1098", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094708", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1099", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094709", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1100", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094710", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen1101", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094711", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1102", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094712", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1103", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094713", + "values_compared": 142 + }, + { + "max_rel_err": 0.0, + "name": "gen1104", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094714", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen1105", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094715", + "values_compared": 116 + }, + { + "max_rel_err": 0.0, + "name": "gen1106", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094716", + "values_compared": 76 + }, + { + "max_rel_err": 0.0, + "name": "gen1107", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094717", + "values_compared": 154 + }, + { + "max_rel_err": 0.0, + "name": "gen1108", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094718", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen1109", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094719", + "values_compared": 118 + }, + { + "max_rel_err": 0.0, + "name": "gen1110", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094720", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1111", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094721", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1112", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094722", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen1113", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094723", + "values_compared": 59 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1114", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094724", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1115", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094725", + "values_compared": 80 + }, + { + "max_rel_err": 0.0, + "name": "gen1116", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094726", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1117", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094727", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen1118", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094728", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen1119", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094729", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1120", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094730", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen1121", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094731", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen1122", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094732", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1123", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094733", + "values_compared": 167 + }, + { + "max_rel_err": 0.0, + "name": "gen1124", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094734", + "values_compared": 152 + }, + { + "max_rel_err": 0.0, + "name": "gen1125", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094735", + "values_compared": 107 + }, + { + "max_rel_err": 0.0, + "name": "gen1126", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094736", + "values_compared": 148 + }, + { + "max_rel_err": 0.0, + "name": "gen1127", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094737", + "values_compared": 139 + }, + { + "max_rel_err": 0.0, + "name": "gen1128", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094738", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen1129", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094739", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen1130", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094740", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen1131", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094741", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen1132", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094742", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1133", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094743", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen1134", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094744", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1135", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094745", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1136", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094746", + "values_compared": 87 + }, + { + "max_rel_err": 0.0, + "name": "gen1137", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094747", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen1138", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094748", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1139", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094749", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1140", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094750", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen1141", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094751", + "values_compared": 125 + }, + { + "max_rel_err": 0.0, + "name": "gen1142", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094752", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1143", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094753", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1144", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094754", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen1145", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094755", + "values_compared": 92 + }, + { + "max_rel_err": 0.0, + "name": "gen1146", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094756", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen1147", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094757", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen1148", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094758", + "values_compared": 177 + }, + { + "max_rel_err": 0.0, + "name": "gen1149", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094759", + "values_compared": 161 + }, + { + "max_rel_err": 0.0, + "name": "gen1150", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094760", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1151", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094761", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen1152", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094762", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1153", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094763", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1154", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094764", + "values_compared": 168 + }, + { + "max_rel_err": 0.0, + "name": "gen1155", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094765", + "values_compared": 93 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1156", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094766", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1157", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094767", + "values_compared": 128 + }, + { + "max_rel_err": 0.0, + "name": "gen1158", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094768", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen1159", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094769", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen1160", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094770", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1161", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094771", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen1162", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094772", + "values_compared": 146 + }, + { + "max_rel_err": 0.0, + "name": "gen1163", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094773", + "values_compared": 56 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1164", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094774", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1165", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094775", + "values_compared": 59 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1166", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094776", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1167", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094777", + "values_compared": 63 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1168", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094778", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1169", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094779", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1170", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094780", + "values_compared": 166 + }, + { + "max_rel_err": 0.0, + "name": "gen1171", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094781", + "values_compared": 147 + }, + { + "max_rel_err": 0.0, + "name": "gen1172", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094782", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1173", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094783", + "values_compared": 69 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1174", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094784", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1175", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094785", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1176", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094786", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen1177", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094787", + "values_compared": 130 + }, + { + "max_rel_err": 0.0, + "name": "gen1178", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094788", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1179", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094789", + "values_compared": 150 + }, + { + "max_rel_err": 0.0, + "name": "gen1180", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094790", + "values_compared": 77 + }, + { + "max_rel_err": 0.0, + "name": "gen1181", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094791", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen1182", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094792", + "values_compared": 150 + }, + { + "max_rel_err": 0.0, + "name": "gen1183", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094793", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen1184", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094794", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen1185", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094795", + "values_compared": 62 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1186", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094796", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1187", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094797", + "values_compared": 116 + }, + { + "max_rel_err": 0.0, + "name": "gen1188", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094798", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen1189", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094799", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1190", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094800", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1191", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094801", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1192", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094802", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen1193", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094803", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen1194", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094804", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen1195", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094805", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1196", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094806", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen1197", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094807", + "values_compared": 150 + }, + { + "max_rel_err": 0.0, + "name": "gen1198", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094808", + "values_compared": 72 + }, + { + "max_rel_err": 0.0, + "name": "gen1199", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094809", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen1200", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094810", + "values_compared": 62 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1201", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094811", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1202", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094812", + "values_compared": 63 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1203", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094813", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1204", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094814", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen1205", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094815", + "values_compared": 132 + }, + { + "max_rel_err": 0.0, + "name": "gen1206", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094816", + "values_compared": 136 + }, + { + "max_rel_err": 0.0, + "name": "gen1207", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094817", + "values_compared": 117 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1208", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094818", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1209", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094819", + "values_compared": 149 + }, + { + "max_rel_err": 0.0, + "name": "gen1210", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094820", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1211", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094821", + "values_compared": 82 + }, + { + "max_rel_err": 0.0, + "name": "gen1212", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094822", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1213", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094823", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen1214", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094824", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen1215", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094825", + "values_compared": 116 + }, + { + "max_rel_err": 0.0, + "name": "gen1216", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094826", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen1217", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094827", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1218", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094828", + "values_compared": 138 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1219", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094829", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1220", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094830", + "values_compared": 155 + }, + { + "max_rel_err": 0.0, + "name": "gen1221", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094831", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1222", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094832", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1223", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094833", + "values_compared": 154 + }, + { + "max_rel_err": 0.0, + "name": "gen1224", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094834", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen1225", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094835", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen1226", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094836", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen1227", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094837", + "values_compared": 148 + }, + { + "max_rel_err": 0.0, + "name": "gen1228", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094838", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1229", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094839", + "values_compared": 157 + }, + { + "max_rel_err": 0.0, + "name": "gen1230", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094840", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1231", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094841", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1232", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094842", + "values_compared": 165 + }, + { + "max_rel_err": 0.0, + "name": "gen1233", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094843", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1234", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094844", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1235", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094845", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1236", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094846", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1237", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094847", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1238", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094848", + "values_compared": 136 + }, + { + "max_rel_err": 0.0, + "name": "gen1239", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094849", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1240", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094850", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1241", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094851", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen1242", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094852", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1243", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094853", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen1244", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094854", + "values_compared": 132 + }, + { + "max_rel_err": 0.0, + "name": "gen1245", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094855", + "values_compared": 76 + }, + { + "max_rel_err": 0.0, + "name": "gen1246", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094856", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1247", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094857", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen1248", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094858", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1249", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094859", + "values_compared": 57 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1250", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094860", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1251", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094861", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen1252", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094862", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1253", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094863", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen1254", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094864", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen1255", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094865", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen1256", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094866", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen1257", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094867", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen1258", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094868", + "values_compared": 115 + }, + { + "max_rel_err": 0.0, + "name": "gen1259", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094869", + "values_compared": 73 + }, + { + "max_rel_err": 0.0, + "name": "gen1260", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094870", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1261", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094871", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1262", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094872", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1263", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094873", + "values_compared": 113 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1264", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094874", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1265", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094875", + "values_compared": 109 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1266", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094876", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1267", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094877", + "values_compared": 107 + }, + { + "max_rel_err": 0.0, + "name": "gen1268", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094878", + "values_compared": 152 + }, + { + "max_rel_err": 0.0, + "name": "gen1269", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094879", + "values_compared": 162 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1270", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094880", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1271", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094881", + "values_compared": 128 + }, + { + "max_rel_err": 0.0, + "name": "gen1272", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094882", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen1273", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094883", + "values_compared": 105 + }, + { + "max_rel_err": 0.0, + "name": "gen1274", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094884", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen1275", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094885", + "values_compared": 129 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1276", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094886", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1277", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094887", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen1278", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094888", + "values_compared": 197 + }, + { + "max_rel_err": 0.0, + "name": "gen1279", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094889", + "values_compared": 82 + }, + { + "max_rel_err": 0.0, + "name": "gen1280", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094890", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1281", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094891", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1282", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094892", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen1283", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094893", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1284", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094894", + "values_compared": 189 + }, + { + "max_rel_err": 0.0, + "name": "gen1285", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094895", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen1286", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094896", + "values_compared": 134 + }, + { + "max_rel_err": 0.0, + "name": "gen1287", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094897", + "values_compared": 65 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1288", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094898", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1289", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094899", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1290", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094900", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1291", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094901", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1292", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094902", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen1293", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094903", + "values_compared": 94 + }, + { + "max_rel_err": 0.0, + "name": "gen1294", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094904", + "values_compared": 64 + }, + { + "max_rel_err": 0.0, + "name": "gen1295", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094905", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1296", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094906", + "values_compared": 71 + }, + { + "max_rel_err": 0.0, + "name": "gen1297", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094907", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen1298", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094908", + "values_compared": 69 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1299", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094909", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1300", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094910", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1301", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094911", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen1302", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094912", + "values_compared": 82 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1303", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094913", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1304", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094914", + "values_compared": 63 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1305", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094915", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1306", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094916", + "values_compared": 77 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1307", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094917", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1308", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094918", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1309", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094919", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen1310", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094920", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen1311", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094921", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1312", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094922", + "values_compared": 127 + }, + { + "max_rel_err": 0.0, + "name": "gen1313", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094923", + "values_compared": 167 + }, + { + "max_rel_err": 0.0, + "name": "gen1314", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094924", + "values_compared": 90 + }, + { + "max_rel_err": 0.0, + "name": "gen1315", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094925", + "values_compared": 91 + }, + { + "max_rel_err": 0.0, + "name": "gen1316", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094926", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1317", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094927", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1318", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094928", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1319", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094929", + "values_compared": 119 + }, + { + "max_rel_err": 0.0, + "name": "gen1320", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094930", + "values_compared": 63 + }, + { + "max_rel_err": 0.0, + "name": "gen1321", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094931", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen1322", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094932", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen1323", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094933", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1324", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094934", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1325", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094935", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1326", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094936", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen1327", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094937", + "values_compared": 150 + }, + { + "max_rel_err": 0.0, + "name": "gen1328", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094938", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1329", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094939", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1330", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094940", + "values_compared": 79 + }, + { + "max_rel_err": 0.0, + "name": "gen1331", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094941", + "values_compared": 62 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1332", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094942", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1333", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094943", + "values_compared": 193 + }, + { + "max_rel_err": 0.0, + "name": "gen1334", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094944", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1335", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094945", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1336", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094946", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen1337", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094947", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1338", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094948", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen1339", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094949", + "values_compared": 172 + }, + { + "max_rel_err": 0.0, + "name": "gen1340", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094950", + "values_compared": 76 + }, + { + "max_rel_err": 0.0, + "name": "gen1341", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094951", + "values_compared": 118 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1342", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094952", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1343", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094953", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen1344", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094954", + "values_compared": 126 + }, + { + "max_rel_err": 0.0, + "name": "gen1345", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094955", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1346", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094956", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1347", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094957", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1348", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094958", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1349", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094959", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen1350", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094960", + "values_compared": 137 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1351", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094961", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1352", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094962", + "values_compared": 132 + }, + { + "max_rel_err": 0.0, + "name": "gen1353", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094963", + "values_compared": 103 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1354", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094964", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1355", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094965", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen1356", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094966", + "values_compared": 72 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1357", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094967", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1358", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094968", + "values_compared": 67 + }, + { + "max_rel_err": 0.0, + "name": "gen1359", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094969", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen1360", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094970", + "values_compared": 90 + }, + { + "max_rel_err": 0.0, + "name": "gen1361", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094971", + "values_compared": 164 + }, + { + "max_rel_err": 0.0, + "name": "gen1362", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094972", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1363", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094973", + "values_compared": 96 + }, + { + "max_rel_err": 0.0, + "name": "gen1364", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094974", + "values_compared": 257 + }, + { + "max_rel_err": 0.0, + "name": "gen1365", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094975", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1366", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094976", + "values_compared": 197 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1367", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094977", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1368", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094978", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1369", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094979", + "values_compared": 150 + }, + { + "max_rel_err": 0.0, + "name": "gen1370", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094980", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1371", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094981", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1372", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094982", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1373", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094983", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen1374", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094984", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1375", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094985", + "values_compared": 116 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1376", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094986", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1377", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094987", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen1378", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094988", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1379", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094989", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen1380", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094990", + "values_compared": 129 + }, + { + "max_rel_err": 0.0, + "name": "gen1381", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094991", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1382", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094992", + "values_compared": 78 + }, + { + "max_rel_err": 0.0, + "name": "gen1383", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094993", + "values_compared": 127 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1384", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005094994", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1385", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094995", + "values_compared": 142 + }, + { + "max_rel_err": 0.0, + "name": "gen1386", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094996", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1387", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094997", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen1388", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094998", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1389", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005094999", + "values_compared": 97 + }, + { + "max_rel_err": 0.0, + "name": "gen1390", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095000", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1391", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095001", + "values_compared": 63 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1392", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005095002", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1393", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095003", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1394", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095004", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen1395", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095005", + "values_compared": 142 + }, + { + "max_rel_err": 0.0, + "name": "gen1396", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095006", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1397", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095007", + "values_compared": 146 + }, + { + "max_rel_err": 0.0, + "name": "gen1398", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095008", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen1399", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095009", + "values_compared": 99 + }, + { + "max_rel_err": 0.0, + "name": "gen1400", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095010", + "values_compared": 197 + }, + { + "max_rel_err": 0.0, + "name": "gen1401", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095011", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1402", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095012", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1403", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095013", + "values_compared": 65 + }, + { + "max_rel_err": 0.0, + "name": "gen1404", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095014", + "values_compared": 105 + }, + { + "max_rel_err": 0.0, + "name": "gen1405", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095015", + "values_compared": 184 + }, + { + "max_rel_err": 0.0, + "name": "gen1406", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095016", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1407", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095017", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1408", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095018", + "values_compared": 123 + }, + { + "max_rel_err": 0.0, + "name": "gen1409", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095019", + "values_compared": 99 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1410", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005095020", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1411", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095021", + "values_compared": 62 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1412", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005095022", + "values_compared": 0 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1413", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005095023", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1414", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095024", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen1415", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095025", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen1416", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095026", + "values_compared": 138 + }, + { + "max_rel_err": 0.0, + "name": "gen1417", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095027", + "values_compared": 90 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1418", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005095028", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1419", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095029", + "values_compared": 87 + }, + { + "max_rel_err": 0.0, + "name": "gen1420", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095030", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1421", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095031", + "values_compared": 186 + }, + { + "max_rel_err": 0.0, + "name": "gen1422", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095032", + "values_compared": 113 + }, + { + "max_rel_err": 0.0, + "name": "gen1423", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095033", + "values_compared": 62 + }, + { + "max_rel_err": 0.0, + "name": "gen1424", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095034", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen1425", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095035", + "values_compared": 163 + }, + { + "max_rel_err": 0.0, + "name": "gen1426", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095036", + "values_compared": 114 + }, + { + "max_rel_err": 0.0, + "name": "gen1427", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095037", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1428", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095038", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen1429", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095039", + "values_compared": 93 + }, + { + "max_rel_err": 0.0, + "name": "gen1430", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095040", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen1431", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095041", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1432", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095042", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen1433", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095043", + "values_compared": 163 + }, + { + "max_rel_err": 0.0, + "name": "gen1434", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095044", + "values_compared": 70 + }, + { + "max_rel_err": 0.0, + "name": "gen1435", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095045", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen1436", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095046", + "values_compared": 57 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1437", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005095047", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1438", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095048", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1439", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095049", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1440", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095050", + "values_compared": 109 + }, + { + "deferred": { + "symbol": "SmSurface::DropCurve", + "unit": "intersect.surface_drop_lib_p3" + }, + "max_rel_err": 0.0, + "name": "gen1441", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005095051", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1442", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095052", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen1443", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095053", + "values_compared": 101 + }, + { + "max_rel_err": 0.0, + "name": "gen1444", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095054", + "values_compared": 103 + }, + { + "max_rel_err": 0.0, + "name": "gen1445", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095055", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1446", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095056", + "values_compared": 159 + }, + { + "max_rel_err": 0.0, + "name": "gen1447", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095057", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1448", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095058", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1449", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095059", + "values_compared": 106 + }, + { + "max_rel_err": 0.0, + "name": "gen1450", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095060", + "values_compared": 160 + }, + { + "max_rel_err": 0.0, + "name": "gen1451", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095061", + "values_compared": 173 + }, + { + "max_rel_err": 0.0, + "name": "gen1452", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095062", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1453", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095063", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen1454", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095064", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1455", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095065", + "values_compared": 84 + }, + { + "max_rel_err": 0.0, + "name": "gen1456", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095066", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1457", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095067", + "values_compared": 122 + }, + { + "max_rel_err": 0.0, + "name": "gen1458", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095068", + "values_compared": 117 + }, + { + "max_rel_err": 0.0, + "name": "gen1459", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095069", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1460", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095070", + "values_compared": 61 + }, + { + "max_rel_err": 0.0, + "name": "gen1461", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095071", + "values_compared": 110 + }, + { + "max_rel_err": 0.0, + "name": "gen1462", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095072", + "values_compared": 85 + }, + { + "max_rel_err": 0.0, + "name": "gen1463", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095073", + "values_compared": 81 + }, + { + "max_rel_err": 0.0, + "name": "gen1464", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095074", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1465", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095075", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1466", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095076", + "values_compared": 117 + }, + { + "max_rel_err": 0.0, + "name": "gen1467", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095077", + "values_compared": 111 + }, + { + "max_rel_err": 0.0, + "name": "gen1468", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095078", + "values_compared": 86 + }, + { + "max_rel_err": 0.0, + "name": "gen1469", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095079", + "values_compared": 104 + }, + { + "max_rel_err": 0.0, + "name": "gen1470", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095080", + "values_compared": 121 + }, + { + "max_rel_err": 0.0, + "name": "gen1471", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095081", + "values_compared": 58 + }, + { + "max_rel_err": 0.0, + "name": "gen1472", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095082", + "values_compared": 59 + }, + { + "max_rel_err": 0.0, + "name": "gen1473", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095083", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen1474", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095084", + "values_compared": 56 + }, + { + "max_rel_err": 0.0, + "name": "gen1475", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095085", + "values_compared": 109 + }, + { + "max_rel_err": 0.0, + "name": "gen1476", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095086", + "values_compared": 69 + }, + { + "max_rel_err": 0.0, + "name": "gen1477", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095087", + "values_compared": 120 + }, + { + "max_rel_err": 0.0, + "name": "gen1478", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095088", + "values_compared": 112 + }, + { + "max_rel_err": 0.0, + "name": "gen1479", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095089", + "values_compared": 68 + }, + { + "max_rel_err": 0.0, + "name": "gen1480", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095090", + "values_compared": 95 + }, + { + "max_rel_err": 0.0, + "name": "gen1481", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095091", + "values_compared": 60 + }, + { + "max_rel_err": 0.0, + "name": "gen1482", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095092", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen1483", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095093", + "values_compared": 133 + }, + { + "max_rel_err": 0.0, + "name": "gen1484", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095094", + "values_compared": 100 + }, + { + "max_rel_err": 0.0, + "name": "gen1485", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095095", + "values_compared": 140 + }, + { + "max_rel_err": 0.0, + "name": "gen1486", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095096", + "values_compared": 135 + }, + { + "max_rel_err": 0.0, + "name": "gen1487", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095097", + "values_compared": 74 + }, + { + "max_rel_err": 0.0, + "name": "gen1488", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095098", + "values_compared": 131 + }, + { + "deferred": { + "symbol": "SmSurface::IsPlanar", + "unit": "surface.surface_p7" + }, + "max_rel_err": 0.0, + "name": "gen1489", + "outcome": "deferred", + "pass": false, + "source": "generated:seed=12145710358005095099", + "values_compared": 0 + }, + { + "max_rel_err": 0.0, + "name": "gen1490", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095100", + "values_compared": 76 + }, + { + "max_rel_err": 0.0, + "name": "gen1491", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095101", + "values_compared": 110 + }, + { + "max_rel_err": 0.0, + "name": "gen1492", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095102", + "values_compared": 124 + }, + { + "max_rel_err": 0.0, + "name": "gen1493", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095103", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen1494", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095104", + "values_compared": 143 + }, + { + "max_rel_err": 0.0, + "name": "gen1495", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095105", + "values_compared": 66 + }, + { + "max_rel_err": 0.0, + "name": "gen1496", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095106", + "values_compared": 57 + }, + { + "max_rel_err": 0.0, + "name": "gen1497", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095107", + "values_compared": 105 + }, + { + "max_rel_err": 0.0, + "name": "gen1498", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095108", + "values_compared": 98 + }, + { + "max_rel_err": 0.0, + "name": "gen1499", + "outcome": "pass", + "pass": true, + "source": "generated:seed=12145710358005095109", + "values_compared": 65 + } + ], + "cases_both_errored": 0, + "cases_deferred": 127, + "cases_failed": 0, + "cases_passed": 1391, + "cases_total": 1518, + "deferred_by_unit": { + "intersect.surface_drop_lib_p3": 83, + "surface.surface_p7": 42, + "surface.surface_p8": 2 + }, + "max_rel_err": 0.0, + "pass": true, + "rel_tol": 1e-9, + "seeds": 16, + "status": "partial", + "unit": "surface.plane_p1" +}