fix: identify user viewports by geometry when id is 0 or negative
The acadrust DWG reader never assigns a viewport id (always 0). Some DXF exporters use id=-1 for all viewports. In both cases the previous id > 1 check excluded every viewport from content rendering. Replace is_user_viewport_id(id) with is_content_viewport(vp) that uses a geometry heuristic for unknown ids (0 / negative): - id=1 → always sheet viewport (excluded) - id≥2 → always user viewport (included) - id=0 or id<0 → sheet if center≈(0,0) AND scale≈1.0, else user This allows DWG files and non-standard DXF files to display model content inside their paper-space viewports and be entered via double-click. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
66a73b00e1
commit
6a0b9169d6
2 changed files with 29 additions and 13 deletions
|
|
@ -1696,7 +1696,7 @@ impl H7CAD {
|
||||||
if let Some(AcadEntityType::Viewport(vp)) =
|
if let Some(AcadEntityType::Viewport(vp)) =
|
||||||
self.tabs[i].scene.document.get_entity(h)
|
self.tabs[i].scene.document.get_entity(h)
|
||||||
{
|
{
|
||||||
if Scene::is_user_viewport_id(vp.id) { Some(h) } else { None }
|
if Scene::is_content_viewport(vp) { Some(h) } else { None }
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -196,14 +196,30 @@ impl Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this viewport ID identifies a user viewport (not the
|
/// Returns true if this viewport should display model-space content
|
||||||
/// sheet/overall viewport). The standard sheet viewport has id=1; id=0
|
/// (i.e. it is a user viewport, not the sheet/overall viewport).
|
||||||
/// means "unset". External DXF exporters sometimes use id=-1 for all
|
///
|
||||||
/// viewports, so any negative id is also treated as a user viewport.
|
/// Rules:
|
||||||
pub fn is_user_viewport_id(id: i16) -> bool {
|
/// - id=1 → always the sheet viewport → false
|
||||||
id != 0 && id != 1
|
/// - id≥2 → always a user viewport → true
|
||||||
|
/// - id=0 or id<0 (DWG reader omits the id; some DXF exporters write -1):
|
||||||
|
/// use geometry: the sheet viewport is centred at the paper origin (0,0)
|
||||||
|
/// with scale≈1.0 (view_height ≈ paper-space height).
|
||||||
|
pub fn is_content_viewport(vp: &acadrust::entities::Viewport) -> bool {
|
||||||
|
if vp.id == 1 { return false; }
|
||||||
|
if vp.id > 1 { return true; }
|
||||||
|
// id=0 or id<0 — distinguish by geometry
|
||||||
|
let scale = if vp.view_height.abs() > 1e-9 {
|
||||||
|
vp.height / vp.view_height
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
let at_origin = vp.center.x.abs() < 0.5 && vp.center.y.abs() < 0.5;
|
||||||
|
let scale_one = (scale - 1.0).abs() < 0.02;
|
||||||
|
!(at_origin && scale_one)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Public accessor for the block-record handle of the current layout.
|
/// Public accessor for the block-record handle of the current layout.
|
||||||
/// Used by external callers (e.g. `commit_entity`) that need the handle
|
/// Used by external callers (e.g. `commit_entity`) that need the handle
|
||||||
/// without going through private API.
|
/// without going through private API.
|
||||||
|
|
@ -333,7 +349,7 @@ impl Scene {
|
||||||
}
|
}
|
||||||
self.document.entities().find_map(|e| {
|
self.document.entities().find_map(|e| {
|
||||||
if let EntityType::Viewport(vp) = e {
|
if let EntityType::Viewport(vp) = e {
|
||||||
if Self::is_user_viewport_id(vp.id) && vp.common.owner_handle == layout_block {
|
if Self::is_content_viewport(vp) && vp.common.owner_handle == layout_block {
|
||||||
let scale = if vp.custom_scale.abs() > 1e-9 {
|
let scale = if vp.custom_scale.abs() > 1e-9 {
|
||||||
vp.custom_scale
|
vp.custom_scale
|
||||||
} else if vp.view_height.abs() > 1e-9 {
|
} else if vp.view_height.abs() > 1e-9 {
|
||||||
|
|
@ -362,7 +378,7 @@ impl Scene {
|
||||||
.entities()
|
.entities()
|
||||||
.filter_map(|e| {
|
.filter_map(|e| {
|
||||||
if let EntityType::Viewport(vp) = e {
|
if let EntityType::Viewport(vp) = e {
|
||||||
if Self::is_user_viewport_id(vp.id) && vp.common.owner_handle == layout_block {
|
if Self::is_content_viewport(vp) && vp.common.owner_handle == layout_block {
|
||||||
Some((vp.common.handle, vp.id, vp.frozen_layers.clone()))
|
Some((vp.common.handle, vp.id, vp.frozen_layers.clone()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -398,7 +414,7 @@ impl Scene {
|
||||||
}
|
}
|
||||||
self.document.entities().filter(|e| {
|
self.document.entities().filter(|e| {
|
||||||
if let EntityType::Viewport(vp) = e {
|
if let EntityType::Viewport(vp) = e {
|
||||||
Self::is_user_viewport_id(vp.id) && vp.common.owner_handle == layout_block
|
Self::is_content_viewport(vp) && vp.common.owner_handle == layout_block
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
@ -802,7 +818,7 @@ impl Scene {
|
||||||
if let EntityType::Viewport(vp) = e { Some(vp) } else { None }
|
if let EntityType::Viewport(vp) = e { Some(vp) } else { None }
|
||||||
})
|
})
|
||||||
.filter(|vp| {
|
.filter(|vp| {
|
||||||
Self::is_user_viewport_id(vp.id)
|
Self::is_content_viewport(vp)
|
||||||
&& vp.common.owner_handle == paper_block
|
&& vp.common.owner_handle == paper_block
|
||||||
&& vp.status.is_on
|
&& vp.status.is_on
|
||||||
&& only_vp.map_or(true, |h| vp.common.handle == h)
|
&& only_vp.map_or(true, |h| vp.common.handle == h)
|
||||||
|
|
@ -1142,7 +1158,7 @@ impl Scene {
|
||||||
.entities()
|
.entities()
|
||||||
.find_map(|e| {
|
.find_map(|e| {
|
||||||
let EntityType::Viewport(vp) = e else { return None; };
|
let EntityType::Viewport(vp) = e else { return None; };
|
||||||
if !Self::is_user_viewport_id(vp.id) || vp.common.owner_handle != layout_block || !vp.status.is_on {
|
if !Self::is_content_viewport(vp) || vp.common.owner_handle != layout_block || !vp.status.is_on {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let hw = (vp.width / 2.0) as f32;
|
let hw = (vp.width / 2.0) as f32;
|
||||||
|
|
@ -1163,7 +1179,7 @@ impl Scene {
|
||||||
let layout_block = self.current_layout_block_handle();
|
let layout_block = self.current_layout_block_handle();
|
||||||
self.document.entities().find_map(|e| {
|
self.document.entities().find_map(|e| {
|
||||||
let EntityType::Viewport(vp) = e else { return None; };
|
let EntityType::Viewport(vp) = e else { return None; };
|
||||||
if Self::is_user_viewport_id(vp.id) && vp.common.owner_handle == layout_block && vp.status.is_on {
|
if Self::is_content_viewport(vp) && vp.common.owner_handle == layout_block && vp.status.is_on {
|
||||||
Some(vp.common.handle)
|
Some(vp.common.handle)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue