CEXT-Dan / PyRx

Python for AutoCAD
42 stars 7 forks source link

Access custom entity content #5

Closed schoeller closed 5 months ago

schoeller commented 6 months ago

Dear all,

thanks for this open source. I am an infrequent scripter accustomed to some python. I have understood that this project aims to make python available from within a CAD environment. I would like to extend my horizon accessing entities custom to Bricscad (TIN, alignment etc.). I have taken testRxPyDebug.py and modified. So I set up an environment whereby I run pystartdebug from Bricscad and run

def PyRxCmd_doit2():
    db = Db.curDb()

    entSelRes = Ed.Editor.entSel("\nPick it")

    print(entSelRes)

I then select a custom entity (TIN entity in this case). When analyzing the locales from the variables output in VS code I can see

Screenshot 2024-03-03 181528

I am wondering as how to access the entity information. If somebody could pinpoint how to access and handle information from this custom entity that would help. Attached is a sample file.

Best regards

Sebastian

BCAD_civil.zip

CEXT-Dan commented 6 months ago

Hi sorry, unfortunately, it’s currently not possible as I have not created wrappers for any verticals or custom objects there was a fork of this project, with the intention of doing exactly this, but it appears to be frozen https://github.com/SioulisChris

I’m not against having BRX specific entities in this project, but I have not thought through it yet. In general wrappers are not hard for me to write, I just don’t know how to use any civil features, so testing could be an issue

def PyRxCmd_doit() -> None:
    try:
        db = Db.curDb()
        entSelRes = Ed.Editor.entSel("\nPick it")
        if entSelRes[0] != Ed.PromptStatus.eOk:
            print("Oops {}: ".format(entSelRes[0]))
            return

        # same as (entget(car(entsel)))
        print(Db.Core.entGet(entSelRes[1]))

    except Exception as err:
        traceback.print_exception(err)

def PyRxCmd_doit2() -> None:
    try:
        db = Db.curDb()
        entSelRes = Ed.Editor.entSel("\nPick it")
        if entSelRes[0] != Ed.PromptStatus.eOk:
            print("Oops {}: ".format(entSelRes[0]))
            return

        # this is the filer from the entity
        # generaly its too hard to read and it's read only
        snoop = Db.SnoopDwgFiler()
        ent = Db.Entity(entSelRes[1])
        ent.snoop(snoop)
        print(snoop.buffer())

    except Exception as err:
        traceback.print_exception(err)
CEXT-Dan commented 6 months ago

I’ve decided to go ahead give this a try. I was able to add CvDbObject, CvDbEntity and CvDbCurve without issues. Hopefully I won't run into any .. Proof of concept, I’ll publish a release when I have something useful. Note, I’m not familiar with the API or Civil

import traceback
from pyrx_imp import Rx
from pyrx_imp import Ge
from pyrx_imp import Gi
from pyrx_imp import Gs
from pyrx_imp import Db
from pyrx_imp import Ap
from pyrx_imp import Ed

from pyrx_imp import Cv

# debug
def PyRxCmd_pydebug() -> None:
    import PyRxDebug
    PyRxDebug.startListener()

def PyRxCmd_doit() -> None:
    try:
        db = Db.curDb()
        entSelRes = Ed.Editor.entSel("\nPick it: ")
        if entSelRes[0] != Ed.PromptStatus.eOk:
            print("Oops {}: ".format(entSelRes[0]))
            return

        id : Db.ObjectId = entSelRes[1]
        if id.isDerivedFrom(Cv.CvDbObject.desc()):
            print("CvDbObject")
            obj = Cv.CvDbObject(id)
            print(obj.name())
            print(obj.description())
        elif id.isDerivedFrom(Cv.CvDbEntity.desc()):
            print("CvDbEntity")
            ent = Cv.CvDbEntity(id)
            print(ent.name())
            print(ent.description())
        elif id.isDerivedFrom(Cv.CvDbCurve.desc()):
            print("CvDbCurve")
            curve = Cv.CvDbCurve(id, Db.OpenMode.kForWrite)
            print(curve.name())
            curve.setDescription("Yahoo Mountain dew")
            print(curve.description())
        else:
            print("oops")

    except Exception as err:
        traceback.print_exception(err)

pof

CEXT-Dan commented 5 months ago

Marking this a closed since it's been added. though there is still work to do

schoeller commented 5 months ago

@CEXT-Dan : I don't know what I am doing, but I am amazed by the magic. Thanks for your work. When scripting in my spare time, should I be posting on theswamp.org or forum.bricsys.com? To me Python + CAD is really spot on, since I'll never learn the LISP syntax. It makes absolute sense to tap onto the multitude of existing Python magic.

CEXT-Dan commented 5 months ago

It’s my pleasure! It started off just as a programing challenge, just to see if I could do it.
I’ll never go back to using lisp again lol. Enjoy!

“should I be posting on theswamp.org or forum.bricsys.com” Bug stuff, missing functions, definitely here, so I can track them. General discussion on the API.. well, it doesn’t matter. It’s a small audience here, where the forums might get answers from more knowledgeable people than me.

Basically, I’m just copy pasting the ARX headers : )

schoeller commented 5 months ago

Am trying to disclose new terrains (to me): When defining an Gi.DrawableOverrule for Cv.CvDbVAlignmentView as such:

#create an overrule     
class AViewDrawOverrule(Gi.DrawableOverrule):
    def __init__(self) -> None:
        Gi.DrawableOverrule.__init__(self)

    # override
    def isApplicable(self, subject) -> bool:
        dbo = Db.Entity.cast(subject)
        return dbo.ownerId() == Db.workingDb().modelSpaceId()

    # override or vpdraw
    def worldDraw(self, subject, wd) -> bool:
        try:
            # draw the subject first
            flag = self.baseWorldDraw(subject, wd)

            #cast
            aview = Cv.CvDbVAlignmentView.cast(subject)
            geo = wd.geometry()
            traits = wd.subEntityTraits()
            traits.setColor(1)

            #do something
            print("VScale="+str(aview.verticalScale()))
            print("HScale="+str(aview.horizontalScale()))
            print("X="+str(aview.origin().x))
            print("Y="+str(aview.origin().y))
            print("Base="+str(aview.baseElevation()))
            print("Name="+aview.name())
            print("Description="+aview.description())
            print("Height="+str(aview.height()))
            print(aview.baseHAlignment())
            for item in aview.getStretchPoints():
                print(item)
            print("Number of graphs contained= " + str(aview.graphCount()))

        except Exception as err:
            traceback.print_exception(err)
        finally:
            return flag

I get

    for item in aview.getStretchPoints():
                ^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: 
Exception!(eNotImplementedYet) in function getStretchPoints, Line 523, File PyDbEntity.cpp: 

Same counts for

    for item in valign.getPVIsArrays():
                ^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: 
Exception!(eInvalidOpenState) in function getPVIsArrays, Line 2435, File PyBrxCvDbAlignments.cpp: 

It's all way above my head, but has me moving (maybe one day this becomes a foundation and I may financially contribute for simple civil application development sigh)

CEXT-Dan commented 5 months ago

Hi, CvDbVAlignment::getPVIsArrays is definitely my bug I have fixed it and added a test, so it will be in the next release.

CvDbVAlignmentView.getStretchPoints is not implemented by Bricsys.

There are two overloads for getGripPoints in BRX, I see one is not implemented by Bricsys, the other I have not implemented because it uses the more complex AcDbGripData class. I will add partial support for AcDbGripData, hopefully enough to collect the geometry

CEXT-Dan commented 5 months ago

I've added an overload for getGripPoints, this can be useful for getting geometry in overrules

def PyRxCmd_doit() -> None:
    try:
        entSelRes = Ed.Editor.entSel("\nPick it: ", Db.Entity.desc())
        if entSelRes[0] != Ed.PromptStatus.eOk:
            print("Oops {}: ".format(entSelRes[0]))
            return

        entity = Db.Entity(entSelRes[1])
        for item in entity.getGripPoints(1.0,1,Ge.Vector3d.kZAxis,0):
            print(item.gripPoint())

    except Exception as err:
        traceback.print_exception(err)

I'll make a new build this afternoon

schoeller commented 4 months ago

out of curiosity and due to not being able to do it myself I was wondering whether it would be possible to access / recreate the properties 1#/2# and entity 3# as per subsequent illustration using PyRx access to BRX. If you fancy experimenting please find the containing sample file attached.

grafik refLabels.zip

CEXT-Dan commented 4 months ago

There may be some possibilities. Ideally you should file a support request for how to do this, and if it’s not implemented, they should add it.

There’s a snooper class you can use, it’s very tedious, cryptic, and read only, but it’s a good way to investigate deep down into objects. You will have to search for the patterns.

import traceback
from pyrx_imp import Rx, Ge, Gi, Db, Ap, Ed

def topsnoop(id):
    alldata = []
    sn = Db.SnoopDwgFiler(Db.FilerType.kCopyFiler)
    obj = Db.DbObject(id)
    obj.snoop(sn)
    alldata.extend(sn.buffer())
    for item in sn:
        if item[0] == "AcDbHardPointerId":
            subsnoop(item[1], alldata)
    return alldata

def subsnoop(id: Db.ObjectId, alldata):
    if not id.isValid():
        return
    nsnoop = Db.SnoopDwgFiler(Db.FilerType.kCopyFiler)
    obj = Db.DbObject(id)
    obj.snoop(nsnoop)
    alldata.extend(nsnoop.buffer())

def PyRxCmd_doit():
    try:
        es = Ed.Editor.entSel("\nSelect")
        alldata = topsnoop(es[1])
        for data in alldata:
            if (data[0] == "ACHAR*"
                and data[1].startswith("<[")
                and data[1].endswith("]>")):
                    print(data[1])
    except Exception as err:
        traceback.print_exception(err)

: DOIT Select<[PointElevation(Um|P2|RN|AP|GS|UN|SN|OF)]>\P<[PointNumber]>\P<[PointFullDescription(CP)]>\P<[RefVAlignment.VAlignmentName(CP)]> : DOIT Select<[PointElevation(Um|P2|RN|AP|GS|UN|SN|OF)]>\P<[PointNumber]>\P<[PointFullDescription(CP)]>\P<[RefHAlignment.AlignmentStationValue(Um|FS|P-1|RN|AP|SN|TP|B3|EY|W0|OF)]>

schoeller commented 4 months ago

Have posted a request under SR-175732 for creating a style from scratch attached to BrxCvDbPointLabelStyleManager.

schoeller commented 4 months ago

Thanks for the work. While turning over my garden compost this morning I was thinking that it'be be handsome to be able to script section entities. Thus one could model a linear solid (for example using an alignment+corridors or arrays+paths) and then generate sections along (cross-sections). Out of curiosity, is it possible to generate sections (ideally section entities usable by the BIM project browser in BCAD) as of now or would this be another custom entity?

CEXT-Dan commented 4 months ago

I haven’t done a whole lot of work on solids, so the wrappers are not 100% complete yet. I had intended to wrap Brep to get access to solid edges and stuff. I’ll probably start on that after I get the stubs and docstrings caught up

I’m not familiar with the any of the BIM stuff in BricsCAD, I know some of that stuff is in BRX I still need to take a look at

schoeller commented 4 months ago

I haven’t done a whole lot of work on solids, so the wrappers are not 100% complete yet. I had intended to wrap Brep to get access to solid edges and stuff. I’ll probably start on that after I get the stubs and docstrings caught up

I’m not familiar with the any of the BIM stuff in BricsCAD, I know some of that stuff is in BRX I still need to take a look at

Thanks for taking the time to answer.

schoeller commented 2 months ago

I haven’t done a whole lot of work on solids, so the wrappers are not 100% complete yet. I had intended to wrap Brep to get access to solid edges and stuff. I’ll probably start on that after I get the stubs and docstrings caught up

I’m not familiar with the any of the BIM stuff in BricsCAD, I know some of that stuff is in BRX I still need to take a look at

@CEXT-Dan hope you're well. Could use functionality to import 1) IFC, 2) classify entities (for example by layer name) and 3) export to IFC. I believe it's all BCAD verticals. I am aware that there may be other priorities. Whenever you find the time I would be grateful to be able to script anything.

1) https://help.bricsys.com/en-us/document/command-reference/i/import-command?version=V24&id=165079082118 2) https://help.bricsys.com/en-us/document/bricscad-bim/building-data/bim-classify?version=V24&id=165079158884 3) https://help.bricsys.com/en-us/document/command-reference/i/ifcexport-command?version=V24&id=165079081611

Have in mind that you're about to travel for longer. Wish you safe journey.

CEXT-Dan commented 2 months ago

Ok, I’ll investigate Brx Bim before starting on Brep. I’m not sure I can get it done before I leave, but I’ll give it a shot