Skip to content

Fix an insert's bounding box to respect its XCLIP boundary - #1226

Open
redbluevn wants to merge 1 commit into
DomCR:masterfrom
redbluevn:moredwg/pr74-insert-clip-bounding-box
Open

redbluevn wants to merge 1 commit into
DomCR:masterfrom
redbluevn:moredwg/pr74-insert-clip-bounding-box

Conversation

@redbluevn

Copy link
Copy Markdown

The problem

A clipped block reference shows only what falls inside its SPATIAL_FILTER boundary, and AutoCAD measures the drawing's extents from what survives the clip. Insert.GetBoundingBox() returned the whole block, so a clipped insert claimed ground the drawing does not occupy.

Measured on a drawing where the block he cot chuan is xclipped:

insert box (before)  (4412478.9, -5391945.3) .. (4441002.3, -5379854.4)
insert box (after)   (4438300.9, -5385917.1) .. (4441002.3, -5379854.4)
AutoCAD's EXTMIN/MAX (4436170,   -5392340)   .. (4477960,   -5362940)

The unclipped box reached about 23,700 units past AutoCAD's own extents, in a drawing only 42,000 units across.

The fix

Intersect the clip boundary with the block's box before the insert transform is applied. An empty intersection is left alone rather than trusted.

One thing worth flagging separately

InverseInsertTransform cannot be used as it is stored.

Both DWG and DXF record it as three rows of four with the translation in the fourth column, and read4x3Matrix / the DXF reader store it exactly that way. Matrix4's own multiplication reads the translation from the fourth row — GetRows() returns the columns of the Mrc grid, and Matrix4.CreateTranslation writes M30/M31/M32.

So matrix * point silently drops the translation, which for a clip boundary is the whole of what the matrix carries. In the drawing above it is a pure translation of (-730293.09, +197002.18, 0), and ignoring it left the boundary a million units from the block, producing an empty intersection and no clip at all.

This PR transposes at the point of use and says why in a comment. Normalising the two matrices at read and write time would be tidier, but it changes a persisted convention in four places (DWG reader and writer, DXF reader and writer) and a per-format round-trip test would not catch a mismatch introduced between the two formats — so it seemed better raised than bundled in here. Nothing else in the library consumes either matrix, which is presumably why this has gone unnoticed.

Tests

New GetBoundingBoxIsClippedByTheSpatialFilter clips a 100x100 block to a 20..60 boundary and gives the filter a translation stored the way a file stores it, so the transpose is exercised rather than assumed. It fails against the current implementation.

dotnet test on this branch: 2314 passed / 17 failed, against 2313 / 17 for master at 592d70a on this machine — the same pre-existing failures plus the one test this PR adds.

Related

#1223, #1224, #1225. With all of them plus DomCR/CSUtilities#23, the computed extents of all eighteen drawings in the sample now agree with AutoCAD's, once entities on frozen layers are excluded as AutoCAD excludes them.

A clipped block reference shows only what is inside its SPATIAL_FILTER boundary,
and AutoCAD measures the drawing's extents from what survives the clip.
GetBoundingBox returned the whole block, so a clipped insert claimed ground the
drawing does not occupy.

The boundary is now intersected with the block's box before the insert transform
is applied. An empty intersection is left alone rather than trusted.

One detail worth flagging: both DWG and DXF record InverseInsertTransform as
three rows of four with the translation in the fourth column, and the readers
store it exactly so - while Matrix4's own multiplication reads the translation
from the fourth ROW. Applied as stored the matrix silently drops its translation,
which for a clip boundary is the whole of what it carries, so it is transposed at
the point of use. Nothing else in the library consumes these two matrices, which
is presumably why the mismatch has gone unnoticed; normalising them at read and
write time would be the tidier fix and is left as a separate question.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant