fix: three measurement defects the adversarial triage surfaced
**COM discarded areas it had already read.** `entity_measure` fell back to rebuilding geometry from `.Coordinates` when `.Area` *or* `.Length` was missing, coupling two independent property reads. HATCH, REGION and 3DSOLID expose `.Area` and neither of the others, so the fallback fired, found no vertices, and raised "AutoCAD reported neither an area nor usable vertices" -- while holding the area. Those are the exact types the README sells the COM backend on. Now only a missing `.Area` triggers the fallback; an absent perimeter is reported as `None` with `perimeter_exact: False` instead of being invented, which also removes a `round(None, 6)` TypeError waiting for the first type that answers `.Area` and nothing else. **A plain square hatch reported itself self-intersecting.** `ezdxf.path .flattening()` repeats the start point, and `is_self_intersecting` excluded adjacent edges *by index*, so with the duplicate present the first and last real edges were cross-tested and registered as crossing. Measured: a 40x40 SOLID hatch came back `area: 1600.0, self_intersecting: True`. A closed loop now answers the same whether or not it carries its closing vertex, and a real bowtie is still caught (`area: 0.0, self_intersecting: True`). **The bowtie warning never fired on the live backend.** `self_intersecting` was only computed inside the COM fallback, so an LWPOLYLINE bowtie -- which has both `.Area` and `.Length` and never reaches it -- returned `area: 0.0, self_intersecting: null`. The confident zero this field exists to flag, going out unflagged. It is now computed on the normal path too. Also corrects a docstring written earlier today in `contracts/analysis.py` claiming the live backend "asks AutoCAD for `.Area`, which has already applied the [hatch island] style". Whether ActiveX's hatch area applies the style is not verified against a live seat, and the method could not measure a hatch at all. It now says so. The ActiveX member profiles behind the COM tests are assumptions, not facts, and the tests say so; a live seat settles them. `.Circumference` for CIRCLE and `.Perimeter` for REGION are deliberately NOT added here -- writing more members from the reference is what produced four wrong beliefs in v1.4/v1.5. 1267 passed, 1 xfailed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
25f8737132
commit
e24b46d6f0
@@ -198,3 +198,39 @@ def test_two_straight_vertices_still_enclose_nothing():
|
||||
|
||||
def test_a_single_vertex_is_still_degenerate():
|
||||
assert polygon_area_perimeter([(0.0, 0.0, 1.0)], closed=True) == (0.0, 0.0)
|
||||
|
||||
|
||||
# ── a closed loop must answer the same however it was handed over ───────────
|
||||
|
||||
|
||||
def test_a_repeated_closing_vertex_is_not_a_self_intersection():
|
||||
"""The false alarm this shipped with.
|
||||
|
||||
`ezdxf.path.flattening()` repeats the start point, so every hatch boundary
|
||||
and every flattened curve arrived here with a duplicate closing vertex. The
|
||||
adjacency guard excludes neighbours *by index*, so the first and last real
|
||||
edges — which share a point but not an index neighbourhood — were
|
||||
cross-tested and reported as crossing. A plain 40x40 square hatch came back
|
||||
`self_intersecting: True`: a confident wrong warning on the field that
|
||||
exists to warn.
|
||||
"""
|
||||
square = [(0.0, 0.0), (50.0, 0.0), (50.0, 50.0), (0.0, 50.0)]
|
||||
|
||||
assert is_self_intersecting(square) is False
|
||||
assert is_self_intersecting([*square, (0.0, 0.0)]) is False
|
||||
|
||||
|
||||
def test_a_bowtie_is_still_caught_when_it_carries_a_closing_vertex():
|
||||
"""Dropping the duplicate must not disarm the check."""
|
||||
bowtie = [(0.0, 0.0), (50.0, 50.0), (50.0, 0.0), (0.0, 50.0)]
|
||||
|
||||
assert is_self_intersecting(bowtie) is True
|
||||
assert is_self_intersecting([*bowtie, (0.0, 0.0)]) is True
|
||||
|
||||
|
||||
def test_a_triangle_with_a_closing_vertex_is_still_not_degenerate():
|
||||
"""Four entries, three real corners — must not fall under the `< 4` guard
|
||||
and answer False for the wrong reason."""
|
||||
triangle = [(0.0, 0.0), (60.0, 0.0), (30.0, 40.0), (0.0, 0.0)]
|
||||
|
||||
assert is_self_intersecting(triangle) is False
|
||||
|
||||
Reference in New Issue
Block a user