forked from 1b-agent/opencadstudio-upstream
feat(solid3d): draw spline (intcurve) edges of ACIS solids
A curved solid's fillet/blend boundaries are `intcurve-curve` spline edges. The edge collector handled only straight and elliptic curves, so a spline edge fell back to a straight chord between its two vertices — or, for a closed-loop edge whose endpoints coincide (a sphere/torus face rim), to nothing at all. Those boundaries simply weren't drawn. Both the feature-edge list and the face-boundary sampler now sample the spline over the edge's own parameter span via the new `SatIntCurve`, so the curved edges draw as real curves. On budweiser2018.dwg handle 2700 the solid's edge-segment count rises from 110 to 392 — the previously missing sphere/torus rim curves. The face-boundary sampler feeding a real loop (instead of a degenerate chord) is also the prerequisite for trimming those curved faces to their extent, a follow-up. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
d80d037e2f
commit
9b7fe2c84d
1 file changed
+31
-2
@@ -15,8 +15,9 @@ use std::f64::consts::TAU;
|
||||
|
||||
use acadrust::entities::acis::types::Sense;
|
||||
use acadrust::entities::acis::{
|
||||
SabReader, SatCoedge, SatConeSurface, SatDocument, SatEdge, SatEllipseCurve, SatFace, SatLoop,
|
||||
SatPlaneSurface, SatPoint, SatPointer, SatSphereSurface, SatTorusSurface, SatVertex,
|
||||
SabReader, SatCoedge, SatConeSurface, SatDocument, SatEdge, SatEllipseCurve, SatFace,
|
||||
SatIntCurve, SatLoop, SatPlaneSurface, SatPoint, SatPointer, SatSphereSurface, SatTorusSurface,
|
||||
SatVertex,
|
||||
};
|
||||
use acadrust::entities::{Body, Region, Solid3D};
|
||||
|
||||
@@ -608,6 +609,15 @@ fn collect_feature_edges(sat: &SatDocument) -> Vec<[f64; 3]> {
|
||||
if let Some(p) = vertex_point(sat, edge.end_vertex()) {
|
||||
pts.push(p);
|
||||
}
|
||||
} else if let Some(ic) = SatIntCurve::from_record(cr) {
|
||||
// Spline edge — sample the actual curve instead of the straight
|
||||
// chord the fallback below would draw (or nothing, for a closed
|
||||
// loop whose endpoints coincide).
|
||||
pts = ic
|
||||
.sample_range(edge.start_param(), edge.end_param(), EDGE_SEGS)
|
||||
.into_iter()
|
||||
.map(|(x, y, z)| [x, y, z])
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
if pts.len() < 2 {
|
||||
@@ -947,6 +957,25 @@ pub(crate) fn append_coedge_points(
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Spline (intcurve) edge: sample its own arc so a curved face boundary
|
||||
// (fillet/blend) is a real loop rather than a straight chord — without
|
||||
// this the face's parametric extent collapses and it can't be trimmed.
|
||||
if let Some(ic) = SatIntCurve::from_record(curve_rec) {
|
||||
let mut sampled: Vec<[f64; 3]> = ic
|
||||
.sample_range(edge.start_param(), edge.end_param(), circ_segs)
|
||||
.into_iter()
|
||||
.map(|(x, y, z)| [x, y, z])
|
||||
.collect();
|
||||
// Drop the shared end point so adjacent coedges don't double up.
|
||||
sampled.pop();
|
||||
if sampled.len() >= 2 {
|
||||
if !fwd {
|
||||
sampled.reverse();
|
||||
}
|
||||
pts.extend(sampled);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Straight / unsupported curve: keep the single start vertex.
|
||||
|
||||
Reference in new issue
Block a user