Skip to content

Commit

Permalink
fix SPATIAL_FILTER group code 71 interpretation
Browse files Browse the repository at this point in the history
  • Loading branch information
mozman committed Jan 14, 2024
1 parent 83cf235 commit 7d302c0
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 53 deletions.
22 changes: 11 additions & 11 deletions docs/source/dxfobjects/spatial_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ The `SPATIAL_FILTER`_ object stores the clipping path for external references an
references. For more information about getting, setting and removing clippings paths
read the docs for the :class:`ezdxf.xclip.XClip` class.

The HEADER variable $XCLIPFRAME determines if the clipping path is displayed and
plotted:

=== ===========================
0 not displayed, not plotted
1 displayed, not plotted
2 displayed and plotted
=== ===========================

.. seealso::

- :mod:`ezdxf.xclip`
Expand All @@ -26,18 +35,9 @@ Factory function internal data structure
Defines the distance of the back clipping plane from the origin in direction of
the extrusion vector.

.. attribute:: dxf.display_clipping_path

The clipping path polygon is visible when 1 and invisible when 0.

The HEADER variable $XCLIPFRAME determines if the clipping path is really
displayed and plotted:
.. attribute:: dxf.is_clipping_enabled

=== ===========================
0 not displayed, not plotted
1 displayed, not plotted
2 displayed and plotted
=== ===========================
Block reference clipping is enabled when 1 and disabled when 0.


.. attribute:: dxf.extrusion
Expand Down
10 changes: 5 additions & 5 deletions docs/source/tools/xclip.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ raise an exception when no clipping path exist.

.. autoproperty:: has_clipping_path

.. autoproperty:: is_clipping_path_visible
.. autoproperty:: is_clipping_enabled

.. autoproperty:: is_inverted_clip

.. automethod:: get_spatial_filter
.. automethod:: disable_clipping

.. automethod:: get_xclip_frame_policy
.. automethod:: enable_clipping

.. automethod:: show_clipping_path
.. automethod:: get_spatial_filter

.. automethod:: hide_clipping_path
.. automethod:: get_xclip_frame_policy

.. automethod:: get_block_clipping_path

Expand Down
11 changes: 11 additions & 0 deletions notes/pages/SPATIAL_FILTER.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ tags:: DXF-Internals
- The clipping path is the geometry entered via the [[XCLIP]] command in OCS coordinates (=WCS in most cases).
- The boundary vertices are transformed into block coordinates by applying the `inverse_insert_matrix`.
-
- ## Visibility of the Clipping Path
- The [[HEADER]] variable [[$XCLIPFRAME]] defines if the clippining polygon is visible
- 0 = not displayed, not plotted
- 1 = displayed, not plotted
- 2 = displayed and plotted
-
- ## Clipping Status
- The group code 71 defines if the state of the block reference clipping
- 0 = off
- 1 = on
-
- ## Inverted Clip Boundary
- There is no flag to indicate an `inverted` clipping boundary
- The regular clipping clipping path, the outer triangle
Expand Down
15 changes: 8 additions & 7 deletions src/ezdxf/addons/drawing/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,9 @@ def draw_insert(insert: Insert):
# Block reference attributes are located __outside__ the block reference!
self.draw_entities(insert.attribs)
clip = xclip.XClip(insert)
if clip.has_clipping_path:
is_clipping_active = clip.has_clipping_path and clip.is_clipping_enabled

if is_clipping_active:
boundary_path = clip.get_wcs_clipping_path()
if not boundary_path.is_inverted_clip:
clipping_shape = clipping_portal.find_best_clipping_shape(
Expand All @@ -842,12 +844,11 @@ def draw_insert(insert: Insert):
)
)

if clip.has_clipping_path:
if clip.is_clipping_path_visible and clip.get_xclip_frame_policy():
self.designer.draw_path(
path=from_vertices(boundary_path.vertices, close=True), # type: ignore
properties=properties,
)
if is_clipping_active and clip.get_xclip_frame_policy():
self.designer.draw_path(
path=from_vertices(boundary_path.vertices, close=True), # type: ignore
properties=properties,
)
self.designer.pop_clipping_shape()

if isinstance(entity, Insert):
Expand Down
16 changes: 8 additions & 8 deletions src/ezdxf/entities/spatial_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@

__all__ = ["SpatialFilter"]

# The HEADER variable $XCLIPFRAME determines if the clipping path polygon is displayed
# and plotted:
# 0 - not displayed, not plotted
# 1 - displayed, not plotted
# 2 - displayed and plotted

logger = logging.getLogger("ezdxf")
AcDbFilter = "AcDbFilter"
AcDbSpatialFilter = "AcDbSpatialFilter"
Expand All @@ -42,13 +48,7 @@
fixer=RETURN_DEFAULT,
),
"origin": DXFAttr(11, xtype=XType.point3d, default=NULLVEC),

# The HEADER variable $XCLIPFRAME determines if the clipping path is really
# displayed and plotted:
# 0 - not displayed, not plotted
# 1 - displayed, not plotted
# 2 - displayed and plotted
"display_clipping_path": DXFAttr(
"is_clipping_enabled": DXFAttr(
71, default=1, validator=validator.is_integer_bool, fixer=RETURN_DEFAULT
),
"has_front_clipping_plane": DXFAttr(
Expand Down Expand Up @@ -183,7 +183,7 @@ def write_matrix(m: Matrix44) -> None:
for vertex in self._boundary_vertices:
tagwriter.write_vertex(10, vertex)
self.dxf.export_dxf_attribs(
tagwriter, ["extrusion", "origin", "display_clipping_path"]
tagwriter, ["extrusion", "origin", "is_clipping_enabled"]
)
has_front_clipping = self.dxf.has_front_clipping_plane
tagwriter.write_tag2(72, has_front_clipping)
Expand Down
18 changes: 9 additions & 9 deletions src/ezdxf/xclip.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ def has_clipping_path(self) -> bool:
return self._spatial_filter is not None

@property
def is_clipping_path_visible(self) -> bool:
"""Returns if the clipping path polygon should be visible in CAD applications."""
def is_clipping_enabled(self) -> bool:
"""Returns ``True`` if block reference clipping is enabled."""
if isinstance(self._spatial_filter, SpatialFilter):
return bool(self._spatial_filter.dxf.display_clipping_path)
return bool(self._spatial_filter.dxf.is_clipping_enabled)
return False

@property
Expand All @@ -113,15 +113,15 @@ def is_inverted_clip(self) -> bool:
return False
return xrec.has_section(ACAD_INVERTEDCLIP_ROUNDTRIP)

def show_clipping_path(self) -> None:
"""Display the clipping path polygon in CAD applications."""
def enable_clipping(self) -> None:
"""Enable block reference clipping."""
if isinstance(self._spatial_filter, SpatialFilter):
self._spatial_filter.dxf.display_clipping_path = 1
self._spatial_filter.dxf.is_clipping_enabled = 1

def hide_clipping_path(self) -> None:
"""Hide the clipping path polygon in CAD applications."""
def disable_clipping(self) -> None:
"""Disable block reference clipping."""
if isinstance(self._spatial_filter, SpatialFilter):
self._spatial_filter.dxf.display_clipping_path = 0
self._spatial_filter.dxf.is_clipping_enabled = 0

def get_block_clipping_path(self) -> ClippingPath:
"""Returns the clipping path in block coordinates (relative to the block origin)."""
Expand Down
2 changes: 1 addition & 1 deletion tests/test_01_dxf_entities/test_143_spatial_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def test_setup_from_tags():
assert len(sp_filter.boundary_vertices) == 2
assert sp_filter.dxf.extrusion == (0, 0, 1)
assert sp_filter.dxf.origin == (0, 0, 0)
assert sp_filter.dxf.display_clipping_path == 1
assert sp_filter.dxf.is_clipping_enabled == 1
assert sp_filter.dxf.has_front_clipping_plane == 0
assert sp_filter.dxf.front_clipping_plane_distance == 0.0
assert sp_filter.dxf.has_back_clipping_plane == 0
Expand Down
24 changes: 12 additions & 12 deletions tests/test_04_dxf_high_level_structs/test_429_xclip.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_rectangular_clipping_path_geometry(clipper: xclip.XClip):

def test_new_spatial_filter_parmeters(clipper: xclip.XClip):
clipper.set_block_clipping_path([(-1, -1), (2, 2)])
assert clipper.is_clipping_path_visible is True
assert clipper.is_clipping_enabled is True
assert clipper.has_clipping_path is True

spatial_filter = clipper.get_spatial_filter()
Expand All @@ -89,22 +89,22 @@ def test_new_spatial_filter_parmeters(clipper: xclip.XClip):
assert spatial_filter.dxf.extrusion == (0, 0, 1)


def test_switch_clipping_path_visibility_without_path(clipper: xclip.XClip):
clipper.show_clipping_path()
assert clipper.is_clipping_path_visible is False
clipper.hide_clipping_path()
assert clipper.is_clipping_path_visible is False
def test_enable_clipping_without_path_set(clipper: xclip.XClip):
clipper.enable_clipping()
assert clipper.is_clipping_enabled is False
clipper.disable_clipping()
assert clipper.is_clipping_enabled is False


def test_switch_clipping_path_visibility(clipper: xclip.XClip):
def test_toggle_clipping_state(clipper: xclip.XClip):
clipper.set_block_clipping_path([(0, 0), (1, 1)])
assert clipper.is_clipping_path_visible is True, "clipping path visible by default"
assert clipper.is_clipping_enabled is True, "clipping path is enabled by default"

clipper.hide_clipping_path()
assert clipper.is_clipping_path_visible is False
clipper.disable_clipping()
assert clipper.is_clipping_enabled is False

clipper.show_clipping_path()
assert clipper.is_clipping_path_visible is True
clipper.enable_clipping()
assert clipper.is_clipping_enabled is True


def test_discard_clipping_path(doc: Drawing):
Expand Down

0 comments on commit 7d302c0

Please sign in to comment.