Find nearby objects with Python

Find nearby objects with Python

A quick example on using cad-pyrx kdtree’s to do a radius search. This is a drawing of a sprinkler system, where the parts are inserted as blocks. The goal is to find all the components within a given radius and list them

from pyrx import Db, Ed, Ge, Ap, Rx, Gs


# create a new command in BricsCAD
@Ap.Command()
def doit():
    try:
        # get modelspace
        db = Db.curDb()
        model = db.modelSpace()

        # get all the block BlockReference
        refs = [Db.BlockReference(id) for id in model.objectIds(Db.BlockReference.desc())]

        # list and map the positions
        allmid = []
        pnt_ref_map = {}
        for ref in refs:
            mid = ref.getGeomExtents().midPoint()
            pnt_ref_map[mid] = ref
            allmid.append(mid)

        # create a kdtree
        tree = Ge.Point3dTree(allmid)

        # search sphere 6"
        rad = 6

        # positions we will search from
        targets = [ref.position() for ref in refs if ref.getBlockName() == "SPK-51-112-1-160-PW"]

        for pnt in targets:
            indexs, dists = tree.radiusSearch(pnt, rad * rad)
            print("\ngroup")
            for idx, dist in zip(indexs, dists):
                if dist == 0:
                    continue
                if allmid[idx] in pnt_ref_map:
                    pnt_ref_map[allmid[idx]].highlight()
                    print(pnt_ref_map[allmid[idx]].getBlockName())

    except Exception as err:
        print(err)

Comments

  • Here’s another example, I want to find all the computers located near a phone

    import traceback
    from pyrx import Ap, Ax, Db, Ed, Ge, Gi, command
    
    # radiusSearch
    @command
    def doit():
        db = Db.curDb()
        phones, computers = getBlocks(db)
        result = []
    
        # create the tree of phone locations
        phonePoints = Ge.Point3dArray()
        for phone in phones:
            phonePoints.append(phone[1])
        phoneTree = Ge.Point3dTree(phonePoints)
    
        # search for nerby phones
        for computer in computers:
            idxs, _ = phoneTree.radiusSearch(computer[1], 50 * 50)# sqrd
            if len(idxs) == 0:
                print("no phone")
                continue
            for idx in idxs:
                result.append((computer, phones[idx]))
    
        for cpu, phn in result:
            Ed.Core.grDraw(cpu[1], phn[1], 2, 0)
    
    
    # helper, store the id and position
    def getBlocks(db: Db.Database):
        phones = []
        computers = []
        model = Db.BlockTableRecord(db.modelSpaceId())
        refs = [Db.BlockReference(id) for id in model.objectIds(Db.BlockReference.desc())]
        for ref in refs:
            if ref.getBlockName() == "COMPUTER":
                computers.append((ref.objectId(), ref.position()))
            elif ref.getBlockName() == "FNPHONE":
                phones.append((ref.objectId(), ref.position()))
        return phones, computers
    

  • ALANH
    edited October 22

    Could not resist, did a "where is" for staff similar method to yours, but added their staff photo to the desk. Used the phone number, a phone block, as the name of the image. Also added a Grid so found me at 5th floor "A1", yes was multiple floors.

    For non Pyhton, use SSget "WP" PTS, just make a list of points based on a centre point and a radius. Very easy using (Polar cenpt rad ang). Just keep incrementing ang with small increments. Say (setq inc (/ (* 2 pi) 20)

  • Its_Alive
    edited October 22

    Sure, you could do this with lisp, the 3D (r3) search might be hard, also performance might become an issue at scale. I used nanoflann, if your interested in the performance characteristics https://github.com/jlblancoc/nanoflann

    My source is here https://github.com/CEXT-Dan/PyRx/blob/main/PyRxCore/PyGePoint3dTree.cpp