mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-10 18:55:14 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fe4027a57 |
+12
-2
@@ -2509,6 +2509,11 @@ pub fn face_intersect_breps_cached(
|
||||
let mut uv_curves1: Vec<Option<Curve>> = Vec::new();
|
||||
let mut uv_curves2: Vec<Option<Curve>> = Vec::new();
|
||||
let mut curve_types: Vec<TsectCurveType> = Vec::new();
|
||||
// Each coincident edge copy's zone: the faces' tolerance, or its edge's when that is
|
||||
// looser (not upstream; solidcraft#11997). A tolerant edge lies off the surfaces as far
|
||||
// as its tolerance says, and classified at the faces' tolerance its crossings with the
|
||||
// other face's edges are missed.
|
||||
let mut curve_zone_tols: Vec<f64> = Vec::new();
|
||||
|
||||
let (are_coincident, coinc_dist) = if let Some(c) = options.coincidence {
|
||||
(c, 0.0)
|
||||
@@ -2541,6 +2546,7 @@ pub fn face_intersect_breps_cached(
|
||||
uv_curves1.push(None);
|
||||
uv_curves2.push(None);
|
||||
curve_types.push(TsectCurveType::RegionBoundary);
|
||||
curve_zone_tols.push(smos_max(zone_tol, edge::tolerance(fb, e)?));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2695,8 +2701,12 @@ pub fn face_intersect_breps_cached(
|
||||
.and_then(Option::as_ref)
|
||||
.map(|_| IntersectObject::UvCurve(ii, true));
|
||||
let ivl = curve.natural_interval();
|
||||
let mut cc1 = curve_classification(k, IntersectObject::Curve(ii), &ivl, uv1, zone_tol)?;
|
||||
let mut cc2 = curve_classification(k, IntersectObject::Curve(ii), &ivl, uv2, zone_tol)?;
|
||||
// surface/surface intersection curves (no entry) are classified at the faces' zone
|
||||
let curve_zone_tol = curve_zone_tols.get(ii).copied().unwrap_or(zone_tol);
|
||||
let mut cc1 =
|
||||
curve_classification(k, IntersectObject::Curve(ii), &ivl, uv1, curve_zone_tol)?;
|
||||
let mut cc2 =
|
||||
curve_classification(k, IntersectObject::Curve(ii), &ivl, uv2, curve_zone_tol)?;
|
||||
|
||||
// the classifications' lazy face queries (UV trim curves, gap caches, tolerance
|
||||
// growth) edit the faces' own B-reps, as upstream's; they are queries, so the
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#![allow(
|
||||
clippy::unwrap_used,
|
||||
clippy::expect_used,
|
||||
clippy::panic,
|
||||
clippy::indexing_slicing
|
||||
)]
|
||||
//! Coincident faces whose edge lies off their surface within its own tolerance
|
||||
//! (solidcraft#11997).
|
||||
//!
|
||||
//! `FaceIntersect` on coincident surfaces copies both faces' edges as the intersection
|
||||
//! curves and classifies each on both faces. A tolerant edge (an imported body's, say) is
|
||||
//! only as close to the surface as its tolerance says: classified at the faces'
|
||||
//! tolerance, its crossings with the other face's edges are missed, and the piece kept is
|
||||
//! wrong. In #11997 the far end of such a piece, off the other face's surface, failed its
|
||||
//! UV solve (status 1001).
|
||||
use solidcore::curve::curve::Curve;
|
||||
use solidcore::curve::line::Line;
|
||||
use solidcore::kernel::KernelOptions;
|
||||
use solidcore::math::{Point3, Vec3};
|
||||
use solidcore::primitive::api_primitives as api;
|
||||
use solidcore::topology::face::p3::{face_intersect_breps, FaceBreps, FaceIntersectOptions};
|
||||
use solidcore::topology::{Brep, EdgeId, FaceId};
|
||||
use solidcore::Kernel;
|
||||
|
||||
/// The face of `b` whose vertices all lie at height `z`.
|
||||
fn face_at(b: &Brep, z: f64) -> FaceId {
|
||||
b.faces()
|
||||
.ids()
|
||||
.find(|&f| {
|
||||
let vs = solidcore::topology::face::p4::vertices(b, f, None, false, None).unwrap();
|
||||
!vs.is_empty()
|
||||
&& vs
|
||||
.iter()
|
||||
.all(|&v| (b.vertex(v).unwrap().point.z - z).abs() < 1e-9)
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// The edge of `b` from (x, 0, z) to (x, 1, z).
|
||||
fn edge_at(b: &Brep, x: f64, z: f64) -> EdgeId {
|
||||
b.edges()
|
||||
.ids()
|
||||
.find(|&e| {
|
||||
b.edge(e).unwrap().vertices.iter().all(|&v| {
|
||||
let p = b.vertex(v).unwrap().point;
|
||||
(p.x - x).abs() < 1e-9 && (p.z - z).abs() < 1e-9
|
||||
})
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coincident_faces_split_a_tolerant_edge_where_it_crosses_the_other_face() {
|
||||
let mut k = Kernel::new(&KernelOptions::default());
|
||||
// A's top (z = 1) over x 0..1, y 0..1; B's over x 0.5..1.5, y 0.25..0.75.
|
||||
let mut a = api::create_box(&mut k, Point3::new(0.0, 0.0, 0.0), 1.0, 1.0, 1.0).unwrap();
|
||||
let mut b = api::create_box(&mut k, Point3::new(0.5, 0.25, 0.0), 1.0, 0.5, 1.0).unwrap();
|
||||
let (fa, fb) = (face_at(&a, 1.0), face_at(&b, 1.0));
|
||||
|
||||
// A's top edge at x = 1, written 5e-5 above the plane, with a tolerance that covers it:
|
||||
// it crosses B's top at y = 0.25 and 0.75, 5e-5 from B's edges there.
|
||||
let dz = 5e-5;
|
||||
let e = edge_at(&a, 1.0, 1.0);
|
||||
let line: Curve = Line::from_points(
|
||||
Vec3::new(1.0, 0.0, 1.0 + dz),
|
||||
Vec3::new(1.0, 1.0, 1.0 + dz),
|
||||
3,
|
||||
)
|
||||
.into();
|
||||
let ends = a.edge(e).unwrap().vertices;
|
||||
for v in ends {
|
||||
let x = a.vertex_mut(v).unwrap();
|
||||
x.point.z += dz;
|
||||
x.tolerance = 1e-3;
|
||||
}
|
||||
let edge = a.edge_mut(e).unwrap();
|
||||
edge.interval = line.natural_interval();
|
||||
edge.curve = Some(line);
|
||||
edge.tolerance = 1e-3;
|
||||
|
||||
let fi = face_intersect_breps(
|
||||
&k,
|
||||
FaceBreps::Two(&mut a, &mut b),
|
||||
fa,
|
||||
fb,
|
||||
1e-6,
|
||||
20.0,
|
||||
&FaceIntersectOptions {
|
||||
coincidence: Some(true),
|
||||
..FaceIntersectOptions::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The pieces of the raised edge kept: inside B's top, y 0.25 to 0.75.
|
||||
let mut kept = Vec::new();
|
||||
for c in &fi.curves_3d {
|
||||
let ivl = c.natural_interval();
|
||||
let (p, q) = (
|
||||
c.evaluate_point(&k, ivl.min()).unwrap(),
|
||||
c.evaluate_point(&k, ivl.max()).unwrap(),
|
||||
);
|
||||
if (p.x - 1.0).abs() < 1e-3 && (q.x - 1.0).abs() < 1e-3 && p.z > 1.0 + dz / 2.0 {
|
||||
kept.push((p.y.min(q.y), p.y.max(q.y)));
|
||||
}
|
||||
}
|
||||
assert_eq!(kept.len(), 1, "{kept:?}");
|
||||
let (lo, hi) = kept[0];
|
||||
assert!(
|
||||
(lo - 0.25).abs() < 1e-3 && (hi - 0.75).abs() < 1e-3,
|
||||
"{kept:?}"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user