forked from 1b-agent/opencadstudio-upstream
fix(solid): normalize quadrilateral edges
Accept perimeter and DXF Z point orders while keeping screen fill and interaction on the WCS-aware geometry. Refs #617
This commit is contained in:
1 parent
6c62daf260
commit
7b50d6a5a3
5 files changed
+151
-70
No files matched your search
+12
-17
@@ -827,6 +827,13 @@ impl Scene {
|
||||
let Some(entity) = self.document.get_entity(handle) else {
|
||||
return true;
|
||||
};
|
||||
// SOLID already renders through its WCS-aware fill triangles.
|
||||
// Its cached HatchModel is an XY-only plot fallback; sending
|
||||
// that to the screen too adds a flattened, grip-less copy at
|
||||
// z=0 for elevated or angled geometry (#617).
|
||||
if matches!(entity, EntityType::Solid(_)) {
|
||||
return false;
|
||||
}
|
||||
let c = entity.common();
|
||||
if c.invisible
|
||||
|| self.entity_temporarily_hidden(handle)
|
||||
@@ -2398,29 +2405,17 @@ impl Scene {
|
||||
}
|
||||
|
||||
/// Build a solid-fill HatchModel for a DXF Solid entity.
|
||||
/// DXF SOLID corners are in "Z-order": p0-p1 top, p2-p3 bottom.
|
||||
/// Visual quad is p0→p1→p3→p2 (closed).
|
||||
/// Conventional DXF SOLID corners use Z-order; legacy entities may already
|
||||
/// be in perimeter order. Use the same non-crossing resolver as wire fill.
|
||||
pub(super) fn solid_hatch_model(solid: &DxfSolid, color: [f32; 4]) -> HatchModel {
|
||||
// Keep the corners in f64 until the AABB centre is known, then store
|
||||
// each as a small f32 offset from it — same precision-preserving anchor
|
||||
// `hatch_model_from_dxf` uses. Casting the absolute WCS corner straight
|
||||
// to f32 costs ~0.06 units of resolution at UTM magnitudes (~1e6), so
|
||||
// the quad snapped to a grid and the fill drifted off its outline.
|
||||
// SOLID corners are stored in OCS (like ARC/LWPOLYLINE) — map through
|
||||
// the arbitrary axis so a mirrored solid (normal 0,0,-1) fills on the
|
||||
// correct side of the drawing.
|
||||
let n = (solid.normal.x, solid.normal.y, solid.normal.z);
|
||||
let w = |v: &acadrust::types::Vector3| -> [f64; 2] {
|
||||
let (x, y, _) =
|
||||
crate::scene::view::transform::ocs_point_to_wcs((v.x, v.y, v.z), n);
|
||||
[x, y]
|
||||
};
|
||||
let corners: [[f64; 2]; 4] = [
|
||||
w(&solid.first_corner),
|
||||
w(&solid.second_corner),
|
||||
w(&solid.fourth_corner),
|
||||
w(&solid.third_corner),
|
||||
];
|
||||
let wcs = crate::entities::solid::wcs_corners(solid);
|
||||
let order = crate::entities::solid::perimeter_indices(&wcs);
|
||||
let corners: [[f64; 2]; 4] = order.map(|index| [wcs[index][0], wcs[index][1]]);
|
||||
let mut min = [f64::INFINITY; 2];
|
||||
let mut max = [f64::NEG_INFINITY; 2];
|
||||
for c in &corners {
|
||||
|
||||
+8
-5
@@ -5989,13 +5989,16 @@ impl Scene {
|
||||
}
|
||||
|
||||
fn hatch_visible_for_interaction(&self, handle: Handle) -> bool {
|
||||
let Some(common) = self
|
||||
.document
|
||||
.get_entity(handle)
|
||||
.map(|entity| entity.common())
|
||||
else {
|
||||
let Some(entity) = self.document.get_entity(handle) else {
|
||||
return false;
|
||||
};
|
||||
// Use the SOLID's WCS-aware wire fill for interaction as well as
|
||||
// drawing. Its cached HatchModel is flattened to XY for plotting and
|
||||
// must not leave an invisible selection target at z=0 (#617).
|
||||
if matches!(entity, EntityType::Solid(_)) {
|
||||
return false;
|
||||
}
|
||||
let common = entity.common();
|
||||
if common.invisible
|
||||
|| self.entity_temporarily_hidden(handle)
|
||||
|| self.layer_hidden(&common.layer)
|
||||
|
||||
@@ -392,6 +392,13 @@ impl Scene {
|
||||
let contextual =
|
||||
crate::scene::annotative::entity_for_active_context(&self.document, source);
|
||||
let entity = contextual.as_ref();
|
||||
// Paper-space SOLIDs already carry WCS-aware wire fill triangles.
|
||||
// Keep their cached XY HatchModel out of the sheet set so the same
|
||||
// entity is not emitted twice (#617). Model fills projected through
|
||||
// floating viewports still use `plot_hatches_for_block` below.
|
||||
if matches!(entity, EntityType::Solid(_)) {
|
||||
continue;
|
||||
}
|
||||
let c = entity.common();
|
||||
if c.invisible
|
||||
|| self.entity_temporarily_hidden(handle)
|
||||
|
||||
Reference in new issue
Block a user