mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-08 04:52:10 +00:00
Merge pull request #1612 from tangency-labs/fix/bspline-surface-cast-subclasses
fix: ports of the SmBSplineSurface cast accept every subclass (cone, sphere, torus, revolution, extrusion)
This commit is contained in:
@@ -105,7 +105,6 @@ use crate::kernel::Kernel;
|
||||
use crate::math::{Point3, Vec3, BIG_DOUBLE, EFF_ZERO, PI};
|
||||
use crate::nurbs::b_spline_curve::BSplineCurve;
|
||||
use crate::nurbs::b_spline_curve_n_lib::TrimMode;
|
||||
use crate::nurbs::b_spline_surface::BSplineSurface;
|
||||
use crate::nurbs::b_spline_surface_n_lib::p2::{EvaluateFlags, OrientType};
|
||||
use crate::nurbs::knots::Side;
|
||||
use crate::surface::plane::Plane;
|
||||
@@ -560,18 +559,6 @@ const fn is_b_spline_kind(c: &Curve) -> bool {
|
||||
)
|
||||
}
|
||||
|
||||
/// `SM_CAST_PTR(SmBSplineSurface, ..)`: the B-spline net of a B-spline surface, a
|
||||
/// plane or a surface of revolution.
|
||||
fn b_spline_net(s: &Surface) -> Option<&BSplineSurface> {
|
||||
match s.kind() {
|
||||
SurfaceKind::BSpline(b) => Some(b),
|
||||
SurfaceKind::Plane(p) => Some(p.base()),
|
||||
SurfaceKind::SurfOfRevolution(r) => Some(r.base()),
|
||||
SurfaceKind::SurfOfExtrusion(r) => Some(r.base()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// `pSurface->DropCurve(crContext, crDomain, cr3dCurve, crInterval, dApproxTol,
|
||||
/// rdMaxDist, rdDeviation, rUVCurves)` with the defaults (`bKeepAllDropCurves =
|
||||
/// TRUE`, no fail record, `bCreatingUVTrimCurve = TRUE`): the UV curves
|
||||
@@ -2430,14 +2417,18 @@ impl FilletBrep {
|
||||
.ok_or_else(|| SolidError::null_pointer(OP))?
|
||||
.clone();
|
||||
let face_srf = &face_srf;
|
||||
let surf_net = b_spline_net(face_srf).ok_or_else(|| SolidError::null_pointer(OP))?;
|
||||
// SM_CAST_PTR(SmBSplineSurface, ..) and NER: every kind derived from
|
||||
// SmBSplineSurface (planes, cones and cylinders, spheres, tori, surfaces of
|
||||
// revolution and extrusion), with the NURB its GetDegree reads
|
||||
let surf_net = crate::topology::brep::p3::with_nurb(k, face_srf)?
|
||||
.ok_or_else(|| SolidError::null_pointer(OP))?;
|
||||
let uv_domain = face_srf.natural_uv_domain_with_nurb(k)?;
|
||||
let tol = face2::tolerance(target, face)?;
|
||||
|
||||
// Determine if we want to work on 2D or 3D
|
||||
let mut project_and_lift = false;
|
||||
let mut create_crv_on_3d = false;
|
||||
let is_plane = match Plane::is_nurb_surface_plane(k, surf_net, 1.0) {
|
||||
let is_plane = match Plane::is_nurb_surface_plane(k, &surf_net, 1.0) {
|
||||
Ok(p) => p.is_some(),
|
||||
Err(err) if err.is_unported() => return Err(err),
|
||||
// an SER status inside is a TRUE return upstream
|
||||
|
||||
@@ -76,7 +76,7 @@ use crate::nurbs::b_spline_curve_n_lib::TrimMode;
|
||||
use crate::nurbs::b_spline_surface::SurfParamType;
|
||||
use crate::nurbs::b_spline_surface_n_lib::p2::EvaluateFlags;
|
||||
use crate::nurbs::knots::Side;
|
||||
use crate::surface::surface::p2::{drop_vectors, TsectCurveType};
|
||||
use crate::surface::surface::p2::{drop_vectors, TsectCurveType, B_SPLINE_SURFACE_TYPE};
|
||||
use crate::surface::surface::{Surface, SurfaceKind};
|
||||
use crate::surface::surface_cache::PatchBoundaryBoundingPlanes;
|
||||
|
||||
@@ -268,11 +268,11 @@ impl SurfaceIntersector<'_> {
|
||||
let surf2 = self.surface(SrfIndex::Second);
|
||||
|
||||
// Control polygons are not available for general surfaces: bail out if not
|
||||
// a BSplineSurface (SM_CAST_PTR(SmBSplineSurface, ..): B-splines and planes;
|
||||
// curve-bounded and STEP surfaces derive from SmSurface only)
|
||||
let is_bss =
|
||||
|s: &Surface| matches!(s.kind(), SurfaceKind::BSpline(_) | SurfaceKind::Plane(_));
|
||||
if !is_bss(surf1) || !is_bss(surf2) {
|
||||
// a BSplineSurface (SM_CAST_PTR(SmBSplineSurface, ..): every kind derived from
|
||||
// it, planes, cones, spheres, tori and surfaces of revolution and extrusion;
|
||||
// curve-bounded, STEP, offset and volume surfaces derive from SmSurface only)
|
||||
let is_bss = |s: &Surface| s.is_kind_of(B_SPLINE_SURFACE_TYPE);
|
||||
if !is_bss(surf1)? || !is_bss(surf2)? {
|
||||
return Ok(BoundaryPlaneTestResult::Unknown);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ use crate::math::{Point3, Vec3, BIG_DOUBLE, EFF_ZERO, EFF_ZERO_SQRT, PI};
|
||||
use crate::query::face::p2::{
|
||||
point_classify_prepared, point_classify_requested, PointClassifyOptions,
|
||||
};
|
||||
use crate::surface::surface::p2::{surface_cache, Surface, SurfaceKind};
|
||||
use crate::surface::surface::p2::{surface_cache, Surface, B_SPLINE_SURFACE_TYPE};
|
||||
use crate::surface::surface_cache::p1::{AltCacheKey, AltSrfCacheType};
|
||||
use crate::surface::trim_srf_cache::POINT_CLASS_UNKNOWN;
|
||||
use crate::topology::face::p2::create_curves_by_trimming_snapshot;
|
||||
@@ -1970,9 +1970,9 @@ pub(super) fn face_silhouettes<O: SolutionObject>(
|
||||
}
|
||||
|
||||
// No cached trimmed silhouette curves in existance -- create them
|
||||
// (SM_CAST_PTR(SmBSplineSurface, pSurface): upstream dereferences NULL for any
|
||||
// other kind)
|
||||
if !matches!(srf.kind(), SurfaceKind::BSpline(_) | SurfaceKind::Plane(_)) {
|
||||
// (SM_CAST_PTR(SmBSplineSurface, pSurface): every kind derived from it; upstream
|
||||
// dereferences NULL for any other kind)
|
||||
if !srf.is_kind_of(B_SPLINE_SURFACE_TYPE)? {
|
||||
return Err(null_deref(
|
||||
OP_FACE_SIL,
|
||||
"face surface is not a B-spline surface",
|
||||
|
||||
@@ -1731,6 +1731,16 @@ impl OffsetExecutive {
|
||||
SurfaceKind::SurfOfExtrusion(surface) if surface.base().gw_nurb().is_none() => {
|
||||
ignore_status(surface.make_nurb(kernel))?;
|
||||
}
|
||||
// (SmCone/SmCylinder, SmSphere and SmTorus are SmBSplineSurfaces too)
|
||||
SurfaceKind::Cone(surface) if surface.rev().base().gw_nurb().is_none() => {
|
||||
ignore_status(surface.make_nurb(kernel))?;
|
||||
}
|
||||
SurfaceKind::Sphere(surface) if surface.base().base().gw_nurb().is_none() => {
|
||||
ignore_status(surface.make_nurb(kernel))?;
|
||||
}
|
||||
SurfaceKind::Torus(surface) if surface.base().base().gw_nurb().is_none() => {
|
||||
ignore_status(surface.make_nurb(kernel))?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let original_faceuse = faceuse;
|
||||
|
||||
@@ -90,7 +90,7 @@ use crate::nurbs::knots::Side;
|
||||
use super::p1::{
|
||||
evaluate_1st_derivatives, get_surface_cache, FindPsNormalEnfo, SurfaceSolveContext,
|
||||
};
|
||||
use super::p2::{LsiGlobalSolver, SurfaceEval};
|
||||
use super::p2::{LsiGlobalSolver, SurfaceEval, B_SPLINE_SURFACE_TYPE};
|
||||
use super::p4::is_point_on_normal;
|
||||
use super::p4::NoObject;
|
||||
use super::p7::{good_drop_result, load_guesses, SpGlobalSolver};
|
||||
@@ -1771,9 +1771,9 @@ impl Surface {
|
||||
};
|
||||
|
||||
let is_plane = |s: &Self| matches!(s.kind(), SurfaceKind::Plane(_));
|
||||
// SM_CAST_PTR(SmBSplineSurface, ..): a plane is one too (tried before)
|
||||
let is_bspline =
|
||||
|s: &Self| matches!(s.kind(), SurfaceKind::BSpline(_) | SurfaceKind::Plane(_));
|
||||
// SM_CAST_PTR(SmBSplineSurface, ..): every kind derived from it (a plane, tried
|
||||
// before, a cone, sphere, torus or surface of revolution or extrusion)
|
||||
let is_bspline = |s: &Self| s.is_kind_of(B_SPLINE_SURFACE_TYPE);
|
||||
let mut tried0 = false;
|
||||
let mut tried1 = false;
|
||||
|
||||
@@ -1842,7 +1842,7 @@ impl Surface {
|
||||
}
|
||||
|
||||
// Next, favor SmBSplineSurfaces.
|
||||
if !tried0 && is_bspline(self) {
|
||||
if !tried0 && is_bspline(self)? {
|
||||
tried0 = true;
|
||||
if try_cover(
|
||||
k,
|
||||
@@ -1857,7 +1857,7 @@ impl Surface {
|
||||
return Ok(done(&mut st, false));
|
||||
}
|
||||
}
|
||||
if !tried1 && is_bspline(other) {
|
||||
if !tried1 && is_bspline(other)? {
|
||||
tried1 = true;
|
||||
if try_cover(
|
||||
k,
|
||||
|
||||
@@ -211,7 +211,12 @@ pub(super) fn invalid(operation: &'static str, reason: &'static str) -> SolidErr
|
||||
/// `SmBSplineSurface` members: an `SmPlane` gives its B-spline part. Callers that
|
||||
/// reach a virtual member deal with planes first.
|
||||
pub(super) fn bspline_of(surface: &Surface) -> Option<&BSplineSurface> {
|
||||
match surface.kind() {
|
||||
bspline_of_kind(surface.kind())
|
||||
}
|
||||
|
||||
/// [`bspline_of`] of a surface kind (a made kind with its NURB, say).
|
||||
fn bspline_of_kind(kind: &SurfaceKind) -> Option<&BSplineSurface> {
|
||||
match kind {
|
||||
SurfaceKind::BSpline(b) => Some(b),
|
||||
SurfaceKind::Plane(p) => Some(p.base()),
|
||||
SurfaceKind::Cone(s) => Some(s.rev().base()),
|
||||
@@ -775,12 +780,22 @@ impl PatchBoundaryBoundingPlanes {
|
||||
let tolerance = 0.0001;
|
||||
|
||||
// local
|
||||
let bs = bspline_of(surface).ok_or(SolidError::null_pointer(OP_PLANES))?;
|
||||
// (the canonical form asks for the NURB through the virtual GetOrCreateGwNurbPointer,
|
||||
// which makes a plane's)
|
||||
let bs = match surface.kind() {
|
||||
bspline_of(surface).ok_or(SolidError::null_pointer(OP_PLANES))?;
|
||||
// (the control point count and the canonical form read the NURB, made through
|
||||
// the virtual GetOrCreateGwNurbPointer when missing: a plane's, a cone's,
|
||||
// sphere's, torus's or surface of revolution's or extrusion's)
|
||||
let bs = match surface.kind_with_nurb(k)? {
|
||||
SurfaceKind::Plane(p) => p.base_for_query(),
|
||||
_ => std::borrow::Cow::Borrowed(bs),
|
||||
SurfaceKind::SurfOfExtrusion(_) => match surface.extrusion_base_with_nurb(k) {
|
||||
Ok(base) => base,
|
||||
Err(e) if e.is_unported() => return Err(e),
|
||||
Err(_) => std::borrow::Cow::Borrowed(
|
||||
bspline_of(surface).ok_or(SolidError::null_pointer(OP_PLANES))?,
|
||||
),
|
||||
},
|
||||
made => std::borrow::Cow::Borrowed(
|
||||
bspline_of_kind(made).ok_or(SolidError::null_pointer(OP_PLANES))?,
|
||||
),
|
||||
};
|
||||
|
||||
// for every boundary
|
||||
|
||||
Reference in New Issue
Block a user