Friday, May 29, 2026

Fine-Tuning Selection Set Filtering with Callbacks in PyRx

As of version 2.2.58, most selection set actions in PyRx have received a powerful overload that allows developers to attach a

When executing a selection command, the callback function automatically intercepts a Db.ObjectIdArray containing the candidate objects. Your logic then evaluates these objects and returns a list of integers representing the indexes of the IDs that should be discarded from the final selection.
Key Benefits of Selection Callbacks
  • Advanced Criteria: Filter by complex properties (like geometric limits or dynamic states) that standard DXF group codes cannot check.
  • Streamlined Workflow: Eliminate the need to manually iterate over and clean up selection sets after user input.
  • Real-time Precision: Ensure your commands only process exactly what they are intended to handle.
The Complete Python Code
Here is how to implement a dynamic block filter using the new callback overload.
 
import traceback
from pyrx import Ap, Db, Ed, Ge, Rx

def dyn_filter(ids: Db.ObjectIdArray) -> list[int]:
    """
    Callback filter that evaluates a list of selected Object IDs.
    Returns a list of list indexes pointing to objects that should be removed.
    """
    itemsToRemove = []
   
    # Enumerate through the selection array to track both index and object ID
    for idx, id in enumerate(ids):
        # Open the ID as a BlockReference to inspect its properties
        ref = Db.BlockReference(id)
       
        # Check if the block reference is NOT a dynamic block
        if not ref.isDynamicBlock():
            # Flag the index for removal if it fails the condition
            itemsToRemove.append(idx)
           
    return itemsToRemove

@Ap.Command()
def pyselectfcb():
    """
    Custom PyRx command to prompt user selection using the custom filter.
    """
    try:
        # Prompt selection filtering for 'INSERT' (Block References)
        # Pass the 'dyn_filter' function as the second argument callback
        ps, ss = Ed.Editor.select([(0, "INSERT")], dyn_filter)
       
        # If the selection prompt was successful, print the result status and size
        if ps == Ed.PromptStatus.eOk:
            print(f"Selection Status: {ps}, Filtered Count: {ss.size()}")
           
    except Exception:
        # Catch and print any runtime exceptions for debugging
        print(traceback.format_exc())


 
Code Walkthrough
  1. Ed.Editor.select Overload: We pass dyn_filter as a functional parameter directly into our selection method.
  2. Indexing Strategy: The callback tracks idx. If a block fails the isDynamicBlock() check, its exact list index is recorded.
  3. Array Cleanup: PyRx reads the returned itemsToRemove list and instantly strips those matching positions out of your final selection set ss.
 
 
Only the Dynamic Blocks are selected, yay!
 

Tuesday, March 26, 2024

TraceBoundary sample in Python for AutoCAD

 

 

import traceback
from pyrx import Ap, Db, Ed, Ge, Gi


@Ap.Command()
def TB() -> None:
    try:
        db = Db.curDb()
        ps, pnt = Ed.Editor.getPoint("\nPick a point")
        if ps != Ed.PromptStatus.eOk:
            return
        for pline in Ed.Editor.traceBoundary(pnt, False):
            pline.setColorIndex(1)
            db.addToCurrentspace(pline)
    except Exception as err:
        traceback.print_exception(err)





 

 

Saturday, February 24, 2024

How to make a Revcloud in Python for AutoCAD

 

There isn’t a “revcloud” entity type in Autocad, but you can make one with a polyline and enlisting the help of send command.  Here’s the sample code

 

import traceback
from pyrx import Ap, Ax, Db, Ed, Ge, Gi


@Ap.Command()
def myrevcloud() -> None:
    try:
        axApp = Ap.Application.acadApplication()
        doc = axApp.activeDocument()
        ms = doc.modelSpace()

        # coords for the cloud and create a polyline
        coords = [
            Ge.Point3d(0, 0, 0),
            Ge.Point3d(0, 1000, 0),
            Ge.Point3d(1000, 1000, 0),
            Ge.Point3d(1000, 0, 0),
            Ge.Point3d(0, 0, 0),
        ]
        pl = ms.addPolyline(coords)

        # use send command to create the revcloud, note the (A)arc length
        handle = '(handent "{}")'.format(pl.handle())
        doc.sendCommand("revcloud A {} Object {} Y ".format(200, handle))
    except Exception as err:
        traceback.print_exception(err)


 

And the result:

 


Sunday, December 10, 2023

Python for AutoCAD, Using shapely to find an oriented bounding box.

 

I see this asked frequently in the AutoCAD forums “How do I get the bounding box of an entity”, and the standard answer is usually, “Use vla-GetBoundingBox”, or get the entity extents. This is the correct answer, caveat, the bounding box is aligned with WCS, so if your object is rotated the result may not be what you need.

 One option is to transform the object to align with WCS. Or we can use a 3rd party tool like Python’s shapely to help. 

 

here's an example:

import traceback
from pyrx import Ap, Ax, Db, Ed, Ge, Gi
from shapely import LineString


@Ap.Command()
def mybb() -> None:
    try:
        # create a selection set filter and select the polylines
        filter = [(Db.DxfCode.kDxfStart, "LWPOLYLINE")]

        ps, ss = Ed.Editor.selectPrompt("\nSelect parts: ", "\nRemove parts: ", filter)
        if ps != Ed.PromptStatus.eNormal:
            return

        # iterate the selection set
        for id in ss:

            # create a LineString from our polylines
            pline = Db.Polyline(id)
            ls = LineString(pline.toList())

            # get the oriented bbox
            coords = ls.oriented_envelope.exterior.coords

            # convert tuples to Ge.Point3d
            points = [Ge.Point3d(p) for p in coords]

            # #draw the results
            Ed.Core.grDraw(points[0], points[1], 1, 0)
            Ed.Core.grDraw(points[1], points[2], 1, 0)
            Ed.Core.grDraw(points[2], points[3], 1, 0)
            Ed.Core.grDraw(points[3], points[0], 1, 0)
    except Exception as err:
        traceback.print_exception(err)




 


 


 

Fine-Tuning Selection Set Filtering with Callbacks in PyRx

As of version 2.2.58, most selection set actions in PyRx have received a powerful overload that allows developers to attach a When executing...