Jump to content

All Activity

This stream auto-updates

  1. Today
  2. GLAVCVS

    Dimensions

    Seneca said: “Homines dum docent discunt.” Which, roughly, means: Learn to explain and explain to learn
  3. GLAVCVS

    Dimensions

    Yes. Part of the problem is with arcs whose initial angle (group 50 in the database) is greater than the final angle (group 51 in the database). But you also have to specify point p2 inside the arc so that it's drawn in the correct location. I had to spend a bit of time figuring this out. (defun C:bm (/ obj num i obj1 db ct rd a1 a2 p1 p2 r ptlist osmant) (setq osmant (getvar "OSMODE")) (setvar "osmode" 0) ; Turn off OSNAP (setq obj (ssget '((0 . "LWPOLYLINE,ARC")))) (setq num (sslength obj)) (setq i 0) (repeat num (setq obj1 (ssname obj i)) (setq db (entget obj1) ptlist (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) db)) ) (if (= (cdr (assoc 0 db)) "ARC") (progn (setq ct (cdr (assoc 10 db))) (setq rd (cdr (assoc 40 db))) (setq a1 (cdr (assoc 50 db)); angulo inicial del arco a2 (cdr (assoc 51 db)); angulo final del arco ) (setq a (if (> a1 a2) (+ a1 (/ (- (* 2. PI) (- a1 a2) ) 2.)) (/ (+ a1 a2) 2.))) (setq p1 (polar ct a1 rd)) (setq p2 (polar ct a (* rd 0.9))) (setq p3 (polar ct a (* rd 1.1))) (command "_.dimradius" "_non" p1 "_non" p2 "") (command "_.dimarc" "_non" p1 "_non" p3 "") ) ;progn ;;; (progn ;polyline arc segment ;;;;;code (foreach l db (if (= (car l) 10) (if p1 (if bulge (progn (command "_.dimradius" "_non" p1 "_non" (cdr l) "") (command "_.dimarc" "_non" p1 "_non" (setq p1 (cdr l)) "") ; ) ) (setq p1 (cdr l)) ) (if (= (car l) 42) (setq bulge (/= (cdr l) 0.0))) ) ) ;progn ) (setq i (1+ i)) ) ;repeat end ; Turn off OSNAP (setvar "osmode" osmant) (princ) )
  4. GLAVCVS

    Dimensions

    The DIMRADIUS and DIMARC commands are very fickle. I've used them very little so far. But thanks to you, I'm a little more familiar with them now. So I guess I owe you a favor for that.
  5. The working database https://help.autodesk.com/view/OARX/2025/ENU/?guid=OARX-RefGuide-AcDbHostApplicationServices__workingDatabase AcDbHostApplicationServices::workingDatabase AcDbHostApplicationServices::setWorkingDatabase It’s mostly legacy stuff at this point; there are some function calls in ObjectARX that do not have a database parameter. They work assuming that that the working database has been set. This is the same sample as above, but we use AutoWorkingDatabase import traceback from pyrx import Db, Ed, Ge, Ap, Rx, Gs from timeit import default_timer as timer from collections import defaultdict def processDWG(allphones: dict[int]): # shortcut to # Db.HostApplicationServices.workingDatabase() db = Db.workingDb() refs = [Db.BlockReference(id) for id in db.objectIds(Db.BlockReference.desc())] for ref in refs: if ref.getBlockName() != "FNPHONE": continue allphones[db.getFilename()] += 1 def readDWG(file: str, allphones): sideDb = Db.Database(False, True) sideDb.readDwgFile(file) sideDb.closeInput(True) # use RAII to set and restore the working db wdb = Db.AutoWorkingDatabase(sideDb) processDWG(allphones) @Ap.Command() def doit(): try: start = timer() # read all text from a collection of drawings allphones = defaultdict(int) for file in Ap.Application.listFilesInPath("E:\\temp", ".dwg"): readDWG(file, allphones) print("Time = {} seconds: ".format(timer() - start)) for k, v in allphones.items(): print(k, v) except Exception as err: traceback.print_exception(err) same output Command: DOIT Time = 0.12193889999980456 seconds: E:\temp\Floor Plan Sample1.dwg 51 E:\temp\Floor Plan Sample2.dwg 51 E:\temp\Floor Plan Sample3.dwg 51 E:\temp\Floor Plan Sample4.dwg 51 E:\temp\Floor Plan Sample5.dwg 51 E:\temp\Floor Plan Sample6.dwg 51 E:\temp\Floor Plan Sample7.dwg 51 E:\temp\Floor Plan Sample8.dwg 51
  6. If you notice, everywhere a class or function returns an objectId collection, you can apply a type filter refs = [Db.BlockReference(id) for id in db.objectIds(Db.BlockReference.desc())]
  7. One thing to keep in mind, is that way python’s garbage collector works; First created, First deleted. We want to break up the functions to ensure that the side database is not deleted before any of it’s objects. This example, we will iterate though all eight files and count the number of phones by floor import traceback from pyrx import Db, Ed, Ge, Ap, Rx, Gs from timeit import default_timer as timer from collections import defaultdict def processDWG(db: Db.Database, allphones: dict[int]): # scan the entire database for blocks, this is a tad slower than just scanning # modelspace refs = [Db.BlockReference(id) for id in db.objectIds(Db.BlockReference.desc())] for ref in refs: if ref.getBlockName() != "FNPHONE": continue allphones[db.getFilename()] += 1 def readDWG(file: str, allphones): # we reading an already created drawing, so change # buildDefaultDrawing: bool = False, # noDocument: bool = True # we want to keep this in a seperate function sideDb = Db.Database(False, True) sideDb.readDwgFile(file) sideDb.closeInput(True) processDWG(sideDb, allphones) @Ap.Command() def doit(): try: start = timer() # read all text from a collection of drawings allphones = defaultdict(int) for file in Ap.Application.listFilesInPath("E:\\temp", ".dwg"): readDWG(file, allphones) print("Time = {} seconds: ".format(timer() - start)) for k, v in allphones.items(): print(k, v) except Exception as err: traceback.print_exception(err) Command: DOIT Time = 0.1402779999998529 seconds: E:\temp\Floor Plan Sample1.dwg 51 E:\temp\Floor Plan Sample2.dwg 51 E:\temp\Floor Plan Sample3.dwg 51 E:\temp\Floor Plan Sample4.dwg 51 E:\temp\Floor Plan Sample5.dwg 51 E:\temp\Floor Plan Sample6.dwg 51 E:\temp\Floor Plan Sample7.dwg 51 E:\temp\Floor Plan Sample8.dwg 51
  8. Yesterday
  9. For these examples, I’ll be working with a folder with copies of the same drawing, pretend they’re floors of the same building or something
  10. You changed label format, the lisp routine trying to sort the strings by extracting the number at the 3rd position L-1 – L32 You will need to fix it to extract the number from XXX-XXX-1(20) The issue is, we don’t know if XXX-XXX will eventually contain a number I.e. A23-ACB-1(20) We don’t know what number you want the labels sorted by. Think about this and report back when you have a standardized label
  11. Trying to add the purple line values will introduce a new problem of overlapping text. trying to remember with CIV3D add extra pts in a long section in particular, one way is add that chainage as part of the alignment. Using say Civil Site Design it has this add extra chainages feature built in. Runs in Civ3D. You can do a mini range start-end chainge, spacing and so on.
  12. Better late the never this will add a " to the end of dimensions for a drawing that is set to IPS. tho doesn't work quite right when tolerances are used. will also prompt you if you are going to overwrite any data Sub addtick() Dim swApp As SldWorks.SldWorks, swModel As SldWorks.ModelDoc2, swDraw As SldWorks.DrawingDoc Dim swView As SldWorks.View, swDispDim As SldWorks.DisplayDimension, swDim As SldWorks.Dimension Dim unitSystem As Long, okRun As Boolean, sCurrSuffix As String, id As String Set swApp = Application.SldWorks Set swModel = swApp.ActiveDoc If swModel Is Nothing Then MsgBox "No active document.", vbExclamation, "Add Inch Tick" Exit Sub End If If swModel.GetType <> swDocDRAWING Then MsgBox "This macro only runs on drawings.", vbExclamation, "Add Inch Tick" Exit Sub End If unitSystem = swModel.Extension.GetUserPreferenceInteger( _ swUserPreferenceIntegerValue_e.swUnitSystem, _ swUserPreferenceOption_e.swDetailingNoOptionSpecified) If unitSystem <> swUnitSystem_e.swUnitSystem_IPS Then MsgBox "This macro will only run in IPS(Inch, Pound, Second) Drawing.", vbExclamation, "Add Inch Tick" Exit Sub End If Set swDraw = swModel Set swView = swDraw.GetFirstView Do While Not swView Is Nothing Set swDispDim = swView.GetFirstDisplayDimension5 Do While Not swDispDim Is Nothing Set swDim = swDispDim.GetDimension sCurrSuffix = swDispDim.GetText(swDimensionTextSuffix) If sCurrSuffix <> "" And Not sCurrSuffix = """" Then If MsgBox("Overwrite """ & sCurrSuffix & """?", vbQuestion + vbYesNo) = vbYes Then swDispDim.SetText swDimensionTextSuffix, """" End If Else swDispDim.SetText swDimensionTextSuffix, """" End If Set swDispDim = swDispDim.GetNext3 Loop Set swView = swView.GetNextView Loop swModel.GraphicsRedraw2 MsgBox "Ticks Added to Drawing" End Sub
  13. Here, I have the profile generated from Civil 3D. The elevations and stations are generated at every 25m interval (white lines), but the crossings are not included. So if I get a lisp that will generate the staion and elevations for the crossings (pink lines) same as the details for the white lines. with your Yval we can get the elevations but need the stations also.
  14. Ooops .. code updated at that post. Here's the problem ( missing parenthesis and color number)
  15. Well, for the DEBUG CONSOLE, I stumbled on the problem when I wasn't searching. I had a filter active. On deleting it, suddenly I saw all the blue reports. Yay!
  16. Worked Great! Thanks for the tip.
  17. Danielm103

    Anatomy of an AcDbObject in Python.

    Best practice for checking types is to use the ObjectId as the AcRxClass is cached when the drawing is opened in CAD. it’s much faster than opening the object db = Db.curDb() for id in db.modelSpace(): if id.isDerivedFrom(Db.Line.desc()): # check the id line = Db.Line(id)
  18. Danielm103

    Anatomy of an AcDbObject in Python.

    Note with casting, the cast internally increases the reference count to the same C++ pointer. If you close one, the other will be closed. Like entangled particles, if Alice changes something, Bob will observe the change line = Db.Line() curve = Db.Curve.cast(line) print(line,curve) #<PyDb.Line object at 0x000001FB834B5940> <PyDb.Curve object at 0x000001FB83577240>
  19. Danielm103

    Anatomy of an AcDbObject in Python.

    Checking Db.Object types and casting Every database object has a static description Db.Line.desc() https://help.autodesk.com/view/OARX/2025/ENU/?guid=OARX-RefGuide-AcRxObject__desc Every database object has an instance method to verify the type https://help.autodesk.com/view/OARX/2025/ENU/?guid=OARX-RefGuide-AcRxObject__isA examples: @Ap.Command() def doit(): try: # check types line = Db.Line() print(line.isA() == Db.Line.desc()) print(line.isA().isDerivedFrom(Db.Line.desc())) print(line.isKindOf(Db.Line.desc())) #check types print(line.isA().isDerivedFrom(Db.Curve.desc())) print(line.isKindOf(Db.Curve.desc())) ps, id, pnt = Ed.Editor.entSel("\nSelect Entity: ") curve = Db.Curve(id) if curve.isKindOf(Db.Line.desc()): #PyRx does not check in the cast cline = Db.Line.cast(curve) print(line.isA() == Db.Line.desc()) print(line.isA().isDerivedFrom(Db.Line.desc())) print(line.isKindOf(Db.Line.desc())) print(line.isA().isDerivedFrom(Db.Curve.desc())) print(line.isKindOf(Db.Curve.desc())) except Exception as err: traceback.print_exception(err) Command: DOIT True True True True True Select Entity: True True True True True
  20. Danielm103

    Anatomy of an AcDbObject in Python.

    The Cons: You have to consider the states of the objects when writing your code, for example function dobad throws an exception Db.ErrorStatusException: Exception!(eWasOpenForRead) because space and model are the same object, to be opened in different states @Ap.Command() def dobad(): try: db = Db.curDb() space = Db.BlockTableRecord(db.modelSpaceId()) for id in space.objectIds(Db.Line.desc()): line = Db.Line(id) # ...... model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForWrite) model.appendAcDbEntity( Db.Line(Ge.Point3d(0, 0, 0), Ge.Point3d(100, 100, 0))) #Db.ErrorStatusException: Exception!(eWasOpenForRead) except Exception as err: traceback.print_exception(err) @Ap.Command() def dogood(): try: db = Db.curDb() space = Db.BlockTableRecord(db.modelSpaceId()) for id in space.objectIds(Db.Line.desc()): line = Db.Line(id) # ...... space.upgradeOpen() # change to write space.appendAcDbEntity( Db.Line(Ge.Point3d(0, 0, 0), Ge.Point3d(100, 100, 0))) except Exception as err: traceback.print_exception(err) @Ap.Command() def dobest(): try: db = Db.curDb() readlines(db) #... writelines(db) except Exception as err: traceback.print_exception(err) def readlines(db): space = Db.BlockTableRecord(db.modelSpaceId()) for id in space.objectIds(Db.Line.desc()): line = Db.Line(id) def writelines(db): model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForWrite) model.appendAcDbEntity( Db.Line(Ge.Point3d(0, 0, 0), Ge.Point3d(100, 100, 0))) best practice is to separate out operations if you run into conflicts
  21. PGia

    Hybrid parallel

    Hi The perpendicular distances to the axis seem to be always the same on both sides of the axis, using only the necessary number of vertices. I think this is what I was looking for. Thank you very much Just one more thing: does the functionality of this code depend on the availability of Express Tools?
  22. Danielm103

    Anatomy of an AcDbObject in Python.

    The Pros: You can leave the entities open for longer, set multiple properties without the overhead of multiple open/close. Consider adding a large number of entities to modelspace, with PyRx, you can leave modelspace opened for write for the entire operation @Ap.Command() def doit(): try: db = Db.curDb() space = Db.BlockTableRecord(db.currentSpaceId(), Db.OpenMode.kForWrite) for idx in range(20): nidx = idx + 100 space.appendAcDbEntity( Db.Line(Ge.Point3d(idx, idx, idx), Ge.Point3d(nidx, nidx, nidx))) except Exception as err: traceback.print_exception(err)
  23. When you call a method against an entity in Lisp or ActiveX, AutoCAD manages the state of the entity for you. The sequence is: - Lock the document - Open the Object kForRead/kForWrite - Perform the operation - Close the Object - Unlock the document The overhead starts to build up if you’re setting lots of dbobject Properties Unlike Lisp or ActiveX, Db.DbObject, in Python, .NET, and ObjectARX you have to manage the object’s lifetime. .NET mainly uses the transaction manager for this, I won’t be getting into that Writing in Python(PyRx) is almost identical to modern C++ in that both systems use smart pointers to help manage the state for you. Consider C++ static void AcRxPyApp_idoit(void) { auto [ps, id, pnt] = entsel(L"\nSelect Entity: "); AcDbEntityPointer pEnt(id, AcDb::OpenMode::kForWrite); pEnt->setLayer(L"0"); } vs Python def doit(): try: ps, id, pnt = Ed.Editor.entSel("\nSelect Entity: ") ent = Db.Entity(id,Db.OpenMode.kForWrite) ent.setLayer("0") except Exception as err: traceback.print_exception(err) In Both C++ and Python, ent (pEnt) is closed at the end of the function scope
  24. I don't tend to annotative dims as much as perhaps I should but will see what I can dig out
  25. I regularly use the attached dynamic block but have a big issue in that I cannot control the attribute text size without having to explode and then individually edit every bock. The attribute is defined with a unique text style and was hoping to use that to control but this does not work, nor does trying to use annotative elements. I tried making the text style annotative, the block it is part of and the dynamic block that contains the sub blocks - no luck. Is there a solution to this? Beam.dwg
  26. SLW210

    Hybrid parallel

    OP's AxisExample.dwg shows DWG file was saved by an application that was not developed or licensed by Autodesk. Both Gian's @GP_ and Daniel's @Danielm103 are still slightly off from @PGia manual examples. With @GP_ CPL I get... Command: CPL Cannot invoke (command) from *error* without prior call to (*push-error-using-command*). Converting (command) calls to (command-s) is recommended. But it runs.. here is OP's (blue) and Gian's (white).
  27. I tried installing this, but I get the following text in the command prompt - "error: extra cdrs in dotted pair on input". Does anyone know how to fix the error?
  1. Load more activity
×
×
  • Create New...