Closed schoeller closed 5 months ago
Hi
cpoint = Cv.CvDbPoint
should be
cpoint = Cv.CvDbPoint()
BTW, I’ll be working on porting the samples from the BRX SDK and adding tests over the next couple weeks There's a few problems I noticed while making the wrappers, an example is conflicting enums. I also am confused on some memory management issues, Bricsys kind of deviated from how ARX works, or it's not clear
I also missed all the BrxCvGis classes, So there’s still work todo
This one is working
def PyRxCmd_do_pointworkflow():
try:
# get the working database, database is also a property of Document
db = Db.HostApplicationServices().workingDatabase()
model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForWrite)
# create a civil point as "firstpoint"
cpoint = Cv.CvDbPoint()
cpoint.setDatabaseDefaults()
cpoint.setEasting(-50)
cpoint.setNorthing(-50)
cpoint.setElevation(-50)
cpoint.setName("firstpoint")
model.appendAcDbEntity(cpoint)
# create a civil point as "point2"
cpoint = Cv.CvDbPoint()
cpoint.setDatabaseDefaults()
cpoint.setEasting(-60)
cpoint.setNorthing(-60)
cpoint.setElevation(-60)
cpoint.setName("point2")
model.appendAcDbEntity(cpoint)
for i in range(108):
cpoint = Cv.CvDbPoint()
cpoint.setDatabaseDefaults()
cpoint.setNumber(i)
cpoint.setEasting(-55 + math.cos(0.2*i)*i)
cpoint.setNorthing(-55 + math.sin(0.2*i)*i)
cpoint.setElevation(i)
cpoint.setName("point" + str(i) + "D3")
model.appendAcDbEntity(cpoint)
except Exception as err:
print(err)
Next stepping stone for me is usage of the pointmanager.
When calling
def PyRxCmd_do_pointgroupworkflow():
try:
# get the working database, database is also a property of Document
db = Db.HostApplicationServices().workingDatabase()
model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForWrite)
manager = Cv.CvDbPointGroupManager()
manager.getManager(db)
except Exception as err:
print(err)
I receive
: DO_POINTGROUPWORKFLOW
Python argument types in
CvDbPointGroupManager.__init__(CvDbPointGroupManager, bool)
did not match C++ signature:
__init__(struct _object * __ptr64, class PyDbObjectId, enum AcDb::OpenMode, bool)
__init__(struct _object * __ptr64, class PyDbObjectId, enum AcDb::OpenMode)
__init__(struct _object * __ptr64, class PyDbObjectId)
So I presume I am scripting incorrectly again. Whenever sample scripts as per BRX API are out it will be of great help. Thanks again.
Here are two samples to get the point CvDbPointGroupManager
Note: I don’t like the name getManager, I’m going to change it to getManagerId for the next release. Just an FYI
def PyRxCmd_doit1(): try: db = Db.curDb() managerid = Cv.CvDbPointGroupManager.getManager(db) #returns an object id manager = Cv.CvDbPointGroupManager(managerid) #id for read print(manager.nextPointNumber()) except Exception as err: print(err) def PyRxCmd_doit2(): try: db = Db.curDb() manager : Cv.CvDbPointGroupManager = Cv.CvDbPointGroupManager.openManager(db, Db.OpenMode.kForRead) print(manager.nextPointNumber()) except Exception as err: print(err)
did as above and then
managerid = Cv.CvDbPointGroupManager.getManagerId(db) #returns an object id
manager = Cv.CvDbPointGroupManager(managerid) #id for read
print(manager.nextPointNumber())
# checking for point group
groupNewId = manager.createPointGroup("NewPointGroup") #returns an object id
groupNew = Cv.CvDbPointGroup(groupNewId) #id for read
print("added new point group")
throws
: DO_POINTGROUPWORKFLOW
111
Exception!(eNullObjectId) in function openAcDbObject, Line66, FilePyDbObjectId.h:
Hi, it appears that CvDbPointGroupManager must be opened for write for createPointGroup to work
db = Db.curDb()
managerid = Cv.CvDbPointGroupManager.getManagerId(db) #returns an object id
manager = Cv.CvDbPointGroupManager(managerid, Db.OpenMode.kForWrite) #id for write
print(manager.nextPointNumber())
# checking for point group
groupNewId = manager.createPointGroup("NewPointGroup") #returns an object id
groupNew = Cv.CvDbPointGroup(groupNewId) #id for read
print(groupNew.name())
print("added new point group")
Hi return and thx. When trying to pass includeNumbers
I stumble next. Have copied the lines from cpp.
# .def("createPointGroup", &PyBrxCvDbPointGroupManager::createPointGroup, DS.ARGS({ "val : str" }))
groupNew = Cv.CvDbPointGroup(groupNewId)
print("added new point group")
# some trouble with passing a str
groupNew.includeNumbers("1-200")
# .def("includeNumbers", &PyBrxCvDbPointGroup::includeNumbers, DS.ARGS())
Python argument types in
CvDbPointGroup.includeNumbers(CvDbPointGroup, int)
did not match C++ signature:
includeNumbers(class PyBrxCvDbPointGroup {lvalue})
Hi, Is should be setIncludeNumbers, and it should be opened for write
def PyRxCmd_doit():
try:
db = Db.curDb()
managerid = Cv.CvDbPointGroupManager.getManagerId(db)
manager = Cv.CvDbPointGroupManager(managerid, Db.OpenMode.kForWrite)
groupNewId = manager.createPointGroup("NewPointGroup")
groupNew = Cv.CvDbPointGroup(groupNewId, Db.OpenMode.kForWrite)
groupNew.setIncludeNumbers("1-200")
print(groupNew.includeNumbers())
except Exception as err:
traceback.print_exception(err)
Started to assemble sample_createalignment from C# / SDK. Have created the horizontal alignment. Next I would like to create a vertical aligment object. Later horizontal and vertical aligment are merged into a 3d alignment. Below is the sample from the SDK.
//Now we can create vertical alignment that uses previously created hAlignment
AlignmentVertical VAlignment = new AlignmentVertical();
VAlignment.SetDatabaseDefaults();
ulong tangentId1 = VAlignment.AddTangentFixed(new Point2d(0.0, 0.0), new Point2d(4.0, 4.0));
ulong tangentId2 = VAlignment.AddTangentFixed(new Point2d(10.0, 8.0), new Point2d(50.0, 4.0));
ulong autoParabola1 = VAlignment.AddParabolaAuto(tangentId1, tangentId2);
VAlignment.BaseHorizontalAlignment = HAlignmentId;
ObjectId VAlignmentId = Utils.AddToModelSpace(VAlignment)[0];
I cannot find the info I expected. Hints kindly appreciated.
Ouch, I totally missed that class! I'll add it now, thank you for pointing that out
Thx for adding the functionality and this vast playground. When adding visuals I stumble as follows.
SDK
HAlignment.TangentExtensionColor = new EntityColor(ColorMethod.ByAci, 4);
HAlignment.Style = HAVisualStyle.Elements | HAVisualStyle.Tangents | HAVisualStyle.Extensions;
PyRx
halignment.setTangentExtensionColor(color.setColorIndex(4))
halignment.setStyle(????)
Seems I am also missing some stubs According to BRX the color values are by ACI
It seems they have made some changes in the .NET API
# get and set alignment element colors; all color values are ACI index colors (0...256)
def PyRxCmd_doit() -> None:
try:
cha = Cv.CvDbHAlignment()
if not cha.setTangentExtensionColor(1): #red
print("\nFailed setTangentExtensionColor")
style = (
Cv.HAlignmentVisualStyle.eElements #0x1
| Cv.HAlignmentVisualStyle.eTangentExtensions #0x2
| Cv.HAlignmentVisualStyle.eElementExtensions #0x4
)
if not cha.setStyle(style):
print("\nFailed setStyle")
print(cha.style() == style)
except Exception as err:
traceback.print_exception(err)
I've added a new .PYI file for civil, it should help a bit. you can replace it with your installed version. There's a high probability that I have made some mistakes so I will be updating it
I had written a post asking for a TIN style overwrite sample. The user hirahira6014 had given an example for batter lines. Since my skills do not suffice I got stuck.
I had asked myself whether it is possible to achieve the TIN task as a loadable python-based plugin using your work. So one would store (a series) of scripts which are loaded at startup through PYLOAD. The user interface is then extented with a style. The style may be used and stored, so that all users having the same python-based plugin environment can reproduce the visuals.
Is this possible and could you image undertaking this adventure and posting an example?
Hi, I think this is far beyond my knowledge. It’s one thing to make wrappers around CIVIL objects / port existing samples, it’s another to understand them. There’s so much of the API I do not understand. I am happy to port exiting samples though.
I had added overrule, caveat, I don’t know how stable it is on BricsCAD as theirs is different than AutoCAD. I’ll try to post a sample of overruling a TIN.
Access to the properties panel isn’t possible, that’s probably beyond the scope of this project
@CEXT-Dan thx for the sample. Am amazed and still struggling.
Have made a sample for Cv.CvGradingSlopeOffsetRule()
which works. Still struggling for making Cv.CvGradingSlopeSurfaceRule() work. Have done
grading = Cv.CvDbGrading()
try:
grading.setInputDataId(pline.objectId())
rule = Cv.CvGradingSlopeSurfaceRule()
rule.setSurfaceId(surfaceId) # passing surface object is
rule.setCutSlope(math.radians(77.0)) # convert deg to rad
rule.setFillSlope(math.radians(77.0)) # convert deg to rad
rule.setSide(Cv.GradingSide.eGradingSideRight)
grading.setRule(rule)
model.appendAcDbEntity(grading)
except:
print("Could not attach gradient object")
the rule contains apparently an error
: SAMP_GRADINGSLOPESURFACE
58691a10
Gradierungsregel fehlt.
Ungültige Eingabedaten.
Hints appreciated.
Hi, I created this using the C++ BRX sample. I don't know what the end result is supposed to look like, I'm having a bit of trouble with the C++ API at the moment
import traceback
from pyrx_imp import Rx
from pyrx_imp import Ge
from pyrx_imp import Gi
from pyrx_imp import Db
from pyrx_imp import Ap
from pyrx_imp import Ed
from pyrx_imp import Gs
from pyrx_imp import Cv
import math
def createSampleTinSurface() -> Cv.CvDbTinSurface:
INNER_OFFSET = 10
OUTER_OFFSET = 50
points = []
points.append(Ge.Point3d(-INNER_OFFSET, -INNER_OFFSET, 0))
points.append(Ge.Point3d(INNER_OFFSET, -INNER_OFFSET, 0))
points.append(Ge.Point3d(INNER_OFFSET, INNER_OFFSET, 0))
points.append(Ge.Point3d(-INNER_OFFSET, INNER_OFFSET, 0))
points.append(Ge.Point3d(-OUTER_OFFSET, -OUTER_OFFSET, -10))
points.append(Ge.Point3d(OUTER_OFFSET, -OUTER_OFFSET, -10))
points.append(Ge.Point3d(OUTER_OFFSET, OUTER_OFFSET, 10))
points.append(Ge.Point3d(-OUTER_OFFSET, OUTER_OFFSET, 10))
pSurface = Cv.CvDbTinSurface()
pSurface.setDatabaseDefaults()
pSurface.initialize(Ge.Point3d(-OUTER_OFFSET, -OUTER_OFFSET, 0),
Ge.Point3d(OUTER_OFFSET, OUTER_OFFSET, 10),
100)
successful = pSurface.addPoints(points)
if not successful:
print("failed @createSampleTinSurface")
pSurface.updateObjectData()
return pSurface
def create3dPolyline() -> Db.Polyline3d:
pline = Db.Polyline3d()
pline.setDatabaseDefaults()
pline.appendVertex(Db.Polyline3dVertex(Ge.Point3d(-5, -20, 1)))
pline.appendVertex(Db.Polyline3dVertex(Ge.Point3d(5, -20, 1)))
pline.appendVertex(Db.Polyline3dVertex(Ge.Point3d(5, 20, 1)))
pline.appendVertex(Db.Polyline3dVertex(Ge.Point3d(-5, 20, 1)))
pline.setClosed(False)
color = Db.Color()
color.setRGB(255, 255, 0)
pline.setColor(color)
return pline
def PyRxCmd_createGradingSlopeSurface():
try:
db = Db.curDb()
surface = createSampleTinSurface()
surfaceId = db.addToModelspace(surface)
polyline = create3dPolyline()
polylineId = db.addToModelspace(polyline)
grading = Cv.CvDbGrading()
stat = grading.setInputDataId(polylineId)
print("\nstatus = {}: ".format(stat))
cutSlope = math.radians(77.0)
fillSlope = math.radians(33.0)
rule = Cv.CvGradingSlopeSurfaceRule(surfaceId,cutSlope,fillSlope)
rule.setSide(Cv.GradingSide.eGradingSideRight)
stat = grading.setRule(rule)
print("\nstatus = {}: ".format(stat))
stat = grading.update(True)
print("\nstatus = {}: ".format(stat))
gradingId = db.addToModelspace(grading)
except Exception as err:
traceback.print_exception(err)
Seems I am also missing some stubs According to BRX the color values are by ACI
It seems they have made some changes in the .NET API
style = ( Cv.HAlignmentVisualStyle.eElements #0x1 | Cv.HAlignmentVisualStyle.eTangentExtensions #0x2 | Cv.HAlignmentVisualStyle.eElementExtensions #0x4 ) if not cha.setStyle(style): print("\nFailed setStyle") print(cha.style() == style)
(Am presuming my way through) I assume that the labeling mechanism available in the civil manager in BCAD is related to objects from CvDbStyleManager as used in the PointSample.py. Do you consider it possible a) creating a new point style programmatically and b) creating new objects filling it with information from existing object either as new civil points or c) even using it on other objects directly (like alignments)?
Yeah, I was considering using the .NET naming convections, the C++ naming is too cryptic I didn’t because its far easier for me to generate wrappers from BRX’s C++ headers.
If I’m understanding the styles correctly, those are database objects and apparently not exposed to BRX. I noted that here https://forum.bricsys.com/discussion/38777/brx-is-the-api-for-civil-brxcv-incomplete#latest
I used the headers from the first version of V24.1, Bricsys has made several fixes since V24.2 But there’s some things I need to consider.
1, If we move to V24.2 libraries, we will break compatibility with V24.1 2, it’s a tremendous amount of work, BRX is missing many thousands of functions. When I first made the port to BRX, I gave up twice https://www.theswamp.org/index.php?topic=58162.msg617161#msg617161 , literally many thousands of lines of code are commented out.
I’ll have a look at the stubs.
@CEXT-Dan maybe their dev-team should get some time first to take action on the pending requests (API-docs + GeoObject crash/SR174355). It is too unfortunate the BRX is cluttering your project. Nobody shall tear on the stability of your art of coding.
HI,
There’s a comment in BRX // get and set alignment element colors; all color values are ACI index colors (0...256)
It seems the .NET wrappers use EntityColor, then convert it. But also, some of these objects also derive from DbEntity Which do have a proper color method, weird
Sorry to bother. Within worldDraw
I am trying to loop through VAlignment elements as follows
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()
for vv in range(0, aview.graphCount()):
valign = Cv.CvDbVAlignment(aview.graphAt(vv))
# looping through alignment elements
for i in range(1, valign.elementCount()+1):
element : Cv.CvDbHAlignmentElement = valign.elementAtId(valign.getElementId(i))
It is failing with below message.
: REGEN
Traceback (most recent call last):
File "C:\Users\Sebastian Schoeller\Documents\GitHub\PyBCv\vAlignView\override_1.py", line 134, in worldDraw
element : Cv.CvDbHAlignmentElement = valign.elementAtId(valign.getElementId(i))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError:
Exception!(eInvalidOpenState) in function elementAtId, Line 2381, File PyBrxCvDbAlignments.cpp:
What I am trying to do is looping through elements within worldDraw
checking for types (line, scs) and drawing blocks according to type. I had managed looping through HAlignment once. This time no luck. Hints appreciated.
this line doesn't seem right for i in range(1, valign.elementCount()+1): it must be out of bounds
According to the API, hAlignment.getElementId(i) wants a GsMarker
It seems Bricsys wants you to use one of their iterators: getUnorderedElementIds firstElementId firstLineElementId
elementId = hAlignment.firstElementId()
while (elementId != 0):
element = hAlignment.elementAtId(elementId)
elementId = element.nextId()
Trying to remove breaklines from a surface (using a helper function to return a list of ids):
1#
def idsFromConstraintList(constraints):
ids=[]
for constraint in constraints:
if Cv.CvDbTinSurfaceConstraint.className == constraint.className:
ids.append(constraint.id())
return ids
2#
constraints = pSurface.getConstraints()
objIds=helper.idsFromConstraintList(constraints)
for id in objIds:
print("\n"+str(id))
try:
pSurface.eraseConstraint(id, True)
print("\nSuccessfully removed constraint with ID: " + id)
except:
print("\nNo constraint removed")
results in
3#
Select TIN Surface:
1007510122
No constraint removed
155
No constraint removed
When calling
4#
pSurface.eraseConstraintsIds(objIds, True)
I get
5#
pSurface.eraseConstraintsIds(objIds, True)
TypeError: No registered converter was able to produce a C++ rvalue of type class PyDbObjectId from this Python object of type int
Try eraseConstraints In Brx there’s two functions that were ambiguous to Python, so I was forced to rename one.
// remove all specified constraints from this TinSurface entity
bool eraseConstraints(const AcArray<Adesk::UInt64>& ids, const bool removeReactor = true);
// removes all specified constraint points from this TinSurface entity
bool eraseConstraints(const AcDbObjectIdArray& entityIds, const bool removeReactor = true);
eraseConstraints is for int id eraseConstraintsIds is for objectid
If it’s too confusing I can rename the functions to something better.. if you have a suggestion maybe eraseConstraintsIntIds eraseConstraintsObjIds
Try eraseConstraints In Brx there’s two functions that were ambiguous to Python, so I was forced to rename one.
// remove all specified constraints from this TinSurface entity bool eraseConstraints(const AcArray<Adesk::UInt64>& ids, const bool removeReactor = true); // removes all specified constraint points from this TinSurface entity bool eraseConstraints(const AcDbObjectIdArray& entityIds, const bool removeReactor = true);
eraseConstraints is for int id eraseConstraintsIds is for objectid
Also not working. Too much for me.
constraints = pSurface.getConstraints()
for constraint in constraints:
match constraint.constraintType():
case Cv.TinConstraintType.eTinBreakline:
print('eTinBreakline')
pSurface.eraseConstraint(constraint.id(), True)
case Cv.TinConstraintType.eTinBoundary:
print('eTinBoundary and do nothing')
case Cv.TinConstraintType.eTinWall:
print('eTinWall')
pSurface.eraseConstraint(constraint.id(), True)
case _:
print('oops')
pSurface.updateConstraint(constraint)
found no of items is correct. in C# sample it says action.Commit();
afterwards. Am I missing something?
What’s the error?
probably requires the surface to be opened for write
try pSurface.upgradeOpen() eraseConstraint... pSurface.updateConstraint(constraint)
just guessing
constraints = pSurface.getConstraints()
pSurface.upgradeOpen()
for constraint in constraints:
---
---
---
pSurface.updateConstraint(constraint)
probably requires the surface to be opened for write
That was it, cheers!
def samp_tinremovebreakline() -> None:
try:
# get database and select entity
db = Db.curDb()
esel = Ed.Editor.entSel("\nSelect TIN Surface: ", Cv.CvDbTinSurface.desc())
if esel[0] != Ed.PromptStatus.eOk:
print("Oops {}: ".format(esel[0]))
return
# get surface object, fetch information and print
pSurface = Cv.CvDbTinSurface(esel[1], Db.OpenMode.kForWrite)
# get surface contstraits and loop
constraints = pSurface.getConstraints()
for constraint in constraints:
match constraint.constraintType():
case Cv.TinConstraintType.eTinBreakline:
print('eTinBreakline')
pSurface.eraseConstraint(constraint.id(), True)
case Cv.TinConstraintType.eTinBoundary:
print('eTinBoundary and do nothing')
case Cv.TinConstraintType.eTinWall:
print('eTinWall')
pSurface.eraseConstraint(constraint.id(), True)
case _:
print('oops')
except Exception as err:
traceback.print_exception(err)
When merging TIN surfaces case 0
works, but case 1
does not. Tried rebuild()
, upgradeOpen()
, no luck.
while True:
ssResult = Ed.Editor.getInteger("\n0 - merge to existing, 1 - create new surface")
if ssResult[0] == Ed.PromptStatus.eNormal :
if ssResult[1] in range(2):
break
match ssResult[1]:
case 0:
try:
fSurface.merge(sSurface)
print("\nMerged second to first surface")
except:
print("\nMerging surfaces failed")
case 1:
try:
nSurface = Cv.CvDbTinSurface()
# nSurface.upgradeOpen()
# nSurface.rebuild()
nSurface.merge(fSurface.merge(sSurface))
# nSurface.merge(sSurface)
db.addToModelspace(nSurface)
print("\nCreating new surface from first and second")
except:
print("\nCreating new surface failed")
Ideas welcome.
C# sample do_TINMesh()
is missing the GetMesh method. Cannot find it.
//TinSurfaceMeshType.TinSurfaceMeshDepth
{
/*
TinSurfaceMeshDepth creates mesh by duplicating the surface vertices (points)
and adding the 'thickness' parameter to the Z-coordinate of duplicated points.
Points are then 'stiched' together to create a closed mesh.
*/
SubDMesh meshAbove = tinSurface.GetMesh(TinSurfaceExtractType.Depth, 1.0);
SubDMesh meshBelow = tinSurface.GetMesh(TinSurfaceExtractType.Depth, -1.0);
if ((meshAbove != null) && (meshBelow != null))
{
meshAbove.ColorIndex = 1;
meshBelow.ColorIndex = 2;
ObjectIdCollection ids = Utils.AddToModelSpace(meshAbove, meshBelow);
}
}
pSurface.subDMesh() ?
pSurface.subDMesh() ?
sorry. wasn't visible in the propositions when typing mesh
. This works for now
mshAbove = pSurface.subDMesh()
for i in range(mshAbove.numOfVertices()):
ver = mshAbove.getVertexAt(i)
ver -= Ge.Vector3d.kZAxis * 1 # substracting 1 to z-axis
mshAbove.setVertexAt(i,ver)
db.addToModelspace(mshAbove)
If I’m understanding the styles correctly, those are database objects and apparently not exposed to BRX. I noted that here https://forum.bricsys.com/discussion/38777/brx-is-the-api-for-civil-brxcv-incomplete#latest
BCAD informed as follows concerning labels:
I see the BrxCvDbObjectManager class has only methods like elementCount(), idAt(), nameAt(), has(), remove(), but there is no add() method yet. This means you cannot create and add new styles from scratch; you can only get or remove existing ones, as exemplified in brxCivilSample\civil_point_sample.cpp.
Are they planning to add it? It seems like a necessary feature
Are they planning to add it? It seems like a necessary feature
Hope so. They stated
[BRX/.NET] Add Civil BRX/.NET API samples so that new labels and symbols can be created from scratch when the related API is completed
Concerning corridor support they stated
There is an existing task: [BRX/.NET] Extend Tin APIs to support Corridor, CorridorTeamplate, CorridorTeamplate, CorridorTemplateElement, and other associated facilities but I am afraid there are no plans for now.
Dear all,
thanks for this adventurous endeavour. I am running Python 3.12, PyRx version <1.2.001.20240310> and BCAD v24. Based on the existing samples I have tried to create a cogo point as follows
as a result the following error is thrown.
Being an occasional scripter my learning curve is mostly driven through code examples and adaptation, so BCAD civil examples are very much appreciated.
Best regards
Sebastian