Skip to content

Instantly share code, notes, and snippets.

@tritao
Last active May 11, 2026 16:10
Show Gist options
  • Select an option

  • Save tritao/428aa6707215112d677825ed9f91dfcb to your computer and use it in GitHub Desktop.

Select an option

Save tritao/428aa6707215112d677825ed9f91dfcb to your computer and use it in GitHub Desktop.
FreeCAD core clipping plane + saved view proposal

FreeCAD Core Clipping Plane + Saved View Proposal

Status: draft for maintainer review

Summary

This proposal recommends two core document objects:

  • App::ClippingPlane as the reusable spatial clipping primitive
  • App::SavedView as the higher-level persisted view-state object

The key design choice is to keep clipping definition separate from saved camera and visibility state.

That split gives us:

  • a general clipping feature usable anywhere in FreeCAD
  • a saved-view workflow comparable to other CAD systems
  • a clean path toward attachment, multiple planes, scoped clipping, and optional OCC-based section geometry later

Design Reference: realthunder

This proposal borrows the user-facing direction of realthunder's SavedView feature, but not its exact storage model.

What to borrow:

  • a first-class SavedView object as the main user-facing "restore this view state" feature
  • partial capture and partial restore instead of forcing one monolithic state bundle
  • draggable clipping-plane interaction and visible plane controls
  • Coin-based runtime clipping for live view analysis

What not to copy directly:

  • clipping existing only as saved view state, with no standalone clipping-plane object
  • hidden dynamic-property bags as the main long-term persistence model
  • hard-coded X/Y/Z/custom plane slots as the core document abstraction
  • restore logic coupled to a specific clipping dialog or widget

Resulting adaptation for core FreeCAD:

  • App::ClippingPlane is the typed, reusable document primitive
  • App::SavedView is the higher-level named view-state object
  • Gui::ClippingPlaneManager owns live per-view Coin clipping state
  • SavedView restores clipping by referencing ClippingPlane objects, not by being the only place where clip definitions exist

Why Two Objects

If clipping exists only as state inside a saved view, it becomes awkward to reuse for:

  • direct interactive clipping without creating a saved view
  • attachment to model references
  • multiple active planes
  • scoped clipping
  • future section/profile generation

If clipping exists only as a standalone plane object, we still miss the user-facing workflow of restoring a named view with camera, visibility, and clipping state together.

So the core model should be:

  • ClippingPlane defines clip geometry and clipping behavior
  • SavedView stores a named view state and may reference zero, one, or many clipping planes

Object Model

1. App::ClippingPlane

Purpose:

  • persistent clipping-plane definition
  • reusable across views and workflows
  • spatial object in the document tree

Base type:

  • App::GeoFeature

Rationale:

  • it already provides Placement
  • it is the right core base for spatial reference objects
  • it avoids introducing a Part dependency just to represent a plane
  • it works naturally with nested placements, groups, and links

v1 persistent properties:

  • Placement from App::GeoFeature
  • Reverse : App::PropertyBool

Likely follow-up properties:

  • Reference : App::PropertyXLinkSub
  • Offset : App::PropertyDistance
  • ScopeMode : App::PropertyEnumeration
  • Targets : App::PropertyXLinkSubList
  • ExtentMode : App::PropertyEnumeration
  • SizeX : App::PropertyLength
  • SizeY : App::PropertyLength

Notes:

  • by default the clip is infinite
  • bounded extents are a follow-up, not a blocker for v1
  • Reference + Offset is the right long-term model for attachment
  • free use without attachment remains plain Placement

2. App::SavedView

Purpose:

  • persistent named view-state object
  • restores camera, visibility, and clipping configuration
  • acts as the user-facing “saved state” feature

Base type:

  • App::DocumentObject

Rationale:

  • it is not a spatial object itself
  • it does not need Placement
  • it is a document-level state container

v2 persistent properties:

  • CameraState : App::PropertyFloatList
  • VisibilityState : App::PropertyMap
  • RestoreCamera : App::PropertyBool
  • RestoreVisibility : App::PropertyBool
  • RestoreClipping : App::PropertyBool
  • ClipPlanes : App::PropertyXLinkList

Possible follow-up properties:

  • display-mode state
  • exploded/hidden/isolation state
  • section-display preferences

Notes:

  • SavedView should reference ClippingPlane objects rather than embedding raw clipping definitions
  • allowing zero clip planes is important, because saved views are useful even without clipping

Gui Architecture

1. Gui::ViewProviderClippingPlane

Files:

  • src/Gui/ViewProviderClippingPlane.h
  • src/Gui/ViewProviderClippingPlane.cpp

Responsibilities:

  • draw the clipping-plane glyph
  • expose view-only display properties
  • provide edit / double-click entry points
  • support manipulator-based interaction later

View properties for ClippingPlane:

  • DisplayLength
  • DisplayHeight
  • ArrowSize
  • LineColor
  • Transparency
  • CutMargin
  • ShowLabel

These are display properties only. They should not define activation state.

2. Gui::ViewProviderSavedView

Files:

  • src/Gui/ViewProviderSavedView.h
  • src/Gui/ViewProviderSavedView.cpp

Responsibilities:

  • tree/object interaction for SavedView
  • context actions such as restore, overwrite, update from current view

This object likely does not need a 3D representation in v1/v2.

3. Gui::ClippingPlaneManager

Files:

  • src/Gui/ClippingPlaneManager.h
  • src/Gui/ClippingPlaneManager.cpp

Responsibilities:

  • maintain runtime activation state per 3D view
  • translate App::ClippingPlane into Coin clip definitions
  • install and remove SoClipPlane nodes
  • react to object edits, deletion, and document close

This manager is the core runtime layer and should be designed from the start to evolve toward:

  • multiple active planes per view
  • scoped clipping
  • saved-view restoration of clip sets

4. Gui::SavedViewController

This can be a small helper rather than a formal public class, but the responsibility needs to exist.

Responsibilities:

  • capture the active view into an App::SavedView
  • restore a saved view into the active 3D view
  • activate referenced clipping planes through ClippingPlaneManager

Runtime State Rules

ClippingPlane activation should be runtime-only, per 3D view.

This state should not be stored on the App::ClippingPlane object.

Why:

  • turning a clip on/off is a session action
  • it should not dirty the document
  • a single clipping plane may be active in one view and inactive in another

Unsaved clipping should also remain runtime-only.

Recommended interaction model:

  • opening the clipping tool creates transient GUI-managed clipping state only
  • closing the tool without saving discards that state
  • saving materializes one or more real document objects such as App::ClippingPlane or App::SavedView

This follows the useful user-facing aspect of the measurement workflow without introducing hidden temporary document objects.

SavedView is different:

  • its persisted contents are part of the document
  • restoring a saved view is a runtime action
  • updating or overwriting a saved view is a document modification

Coin vs OCC

Visual clipping should be handled by Coin:

  • SoClipPlane
  • optionally SoClipPlaneManip

OCC is not required for:

  • live clipping
  • attached or free clip-plane placement
  • saved views restoring clip state

OCC should only enter when we want:

  • section profiles
  • capped cut faces
  • filled cut geometry
  • parametric section result objects

Proposed PR Sequence

PR1: ClippingPlane Primitive

Goal:

  • land a core App::ClippingPlane and Gui::ViewProviderClippingPlane
  • land a Gui::ClippingPlaneManager
  • support Coin-based whole-document clipping
  • support one active clipping plane per 3D view

Included:

  • create/delete/save/restore clipping plane
  • edit placement
  • reverse direction
  • activate/deactivate in active 3D view
  • visual plane glyph

Excluded:

  • SavedView
  • attachment
  • scope filtering
  • multi-plane activation
  • geometry generation

Files for PR1:

App:

  • src/App/ClippingPlane.h
  • src/App/ClippingPlane.cpp
  • src/App/CMakeLists.txt

Gui:

  • src/Gui/ViewProviderClippingPlane.h
  • src/Gui/ViewProviderClippingPlane.cpp
  • src/Gui/ClippingPlaneManager.h
  • src/Gui/ClippingPlaneManager.cpp
  • src/Gui/TaskClippingPlane.h
  • src/Gui/TaskClippingPlane.cpp
  • src/Gui/TaskClippingPlane.ui
  • src/Gui/CommandView.cpp
  • src/Gui/CMakeLists.txt
  • icon/resource registration files

Tests:

  • src/Mod/Test/TestClipPlaneApp.py
  • src/Mod/Test/TestClipPlaneGui.py

Acceptance criteria:

  • clipping plane can be created from GUI
  • object appears in tree
  • placement changes update the displayed plane
  • activation clips the active 3D view
  • reverse flips the clipped side
  • save/reopen preserves definition
  • activation does not dirty the document

PR2: SavedView Object

Goal:

  • introduce a core App::SavedView
  • persist named view states
  • allow restoring one or more referenced clipping planes as part of that state

Included:

  • create saved view from current active view
  • restore camera and visibility
  • restore clipping through ClippingPlaneManager
  • overwrite/update a saved view

Files for PR2:

App:

  • src/App/SavedView.h
  • src/App/SavedView.cpp
  • src/App/CMakeLists.txt

Gui:

  • src/Gui/ViewProviderSavedView.h
  • src/Gui/ViewProviderSavedView.cpp
  • src/Gui/TaskSavedView.h
  • src/Gui/TaskSavedView.cpp
  • command wiring and icon/resource registration

Tests:

  • src/Mod/Test/TestSavedViewApp.py
  • src/Mod/Test/TestSavedViewGui.py

Acceptance criteria:

  • saved view persists camera and visibility state
  • saved view can reference clip planes
  • restoring a saved view activates the referenced clip planes in the current 3D view

PR3: Attachment, Offset, and Size

Goal:

  • make clip planes practical for model-driven workflows

Included:

  • Reference
  • Offset
  • free vs attached manipulation behavior
  • SizeX / SizeY or equivalent bounded extents model

Interaction model:

  • attached plane: manipulator primarily edits offset and local transform
  • unattached plane: manipulator edits placement directly

PR4: Multiple Planes and Compound Clipping

Goal:

  • support multiple active clipping planes per view
  • enable “quarter cut” and similar workflows

Included:

  • manager-side support for clip sets
  • SavedView references to multiple clip planes
  • activation rules for multiple planes in one view

PR5: OCC Section Geometry

Goal:

  • optional generated section/profile outputs

Included:

  • section profile object generation
  • capped/fill-ready geometry
  • future downstream use in documentation workflows

Tests

App Tests

TestClipPlaneApp.py

  • create App::ClippingPlane
  • verify default properties
  • verify Placement persistence
  • verify Reverse persistence

TestSavedViewApp.py

  • create App::SavedView
  • verify camera and clip-plane reference persistence
  • verify update/overwrite behavior

Gui Tests

TestClipPlaneGui.py

  • create object through command
  • activate/deactivate in a 3D view
  • verify activation does not mark the document modified
  • verify deleting an active clipping plane cleans up runtime state

TestSavedViewGui.py

  • capture current view to a saved view
  • restore saved view
  • verify restored camera state
  • verify referenced clip planes are activated through the manager

Main Review Questions

  1. Do we agree with using realthunder's SavedView as the UX precedent for the user-facing feature?
  2. Do we agree with intentionally diverging from that implementation by introducing a typed App::ClippingPlane, instead of keeping clipping only as state inside SavedView?
  3. Is App::GeoFeature the right base type for App::ClippingPlane?
  4. Is App::DocumentObject the right base type for App::SavedView?
  5. Is it acceptable that ClippingPlane activation remains runtime-only and per-view?
  6. Should SavedView reference clip planes rather than embed raw clip definitions?
  7. Is one active clipping plane per view acceptable for PR1 if the manager is designed to expand later?
  8. Is the proposed sequencing acceptable: ClippingPlane first, SavedView second?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment