Extracting connection points coordinates of Autocad MEP objects

Extracting connection points coordinates of Autocad MEP objects

andkal
Collaborator Collaborator
2,120 Views
11 Replies
Message 1 of 12

Extracting connection points coordinates of Autocad MEP objects

andkal
Collaborator
Collaborator

Hi

Does anyone know how to extract via lisp the connection points coordinates of AutoCad Mep objects?

I don't mean simple duct or pipe -becouse start and end point of those objects I can get by "vlax-dump-object" - but tees, elbows and other fittings and equipment objects.

List (autocad command) can display that information in textscreen but from there the coordinates can only be copied manually.

I want to assign those coordinates to a variable
Thanks for any help


• www.autolisps.blogspot.com - Productivity plugins for Autocad and Autocad MEP
• Autodesk AppStore
0 Likes
Accepted solutions (1)
2,121 Views
11 Replies
Replies (11)
Message 2 of 12

devitg
Advisor
Advisor

Please upload a sample DWG . 

Message 3 of 12

andkal
Collaborator
Collaborator

Please find attached dwg.
Below - screenshot showing that I ment.
Ventilation_tee.JPG


• www.autolisps.blogspot.com - Productivity plugins for Autocad and Autocad MEP
• Autodesk AppStore
0 Likes
Message 4 of 12

dbroad
Mentor
Mentor

You're most likely wasting time. These kinds of objects are unsupported by LISP.  If you seriously need these items you probably need to learn .NET.  If you join the ADN network, you might learn how to access the API for these objects.

 

This might give you a start:

 

http://adndevblog.typepad.com/aec/2012/07/where-is-autocad-mep-sdk.html

Architect, Registered NC, VA, SC, & GA.
Message 5 of 12

andkal
Collaborator
Collaborator
Accepted solution

Thanks to devitg, who suggested me using logfile to read what "list" (autocad dommand) returns I managed to write a lisp that retrieves connection points of pipefittings, ductfittings and cabeltrayfittings. Also if I wanted to retrieve just one connection point of the picked end of the fitting, there is a simplier method - before entsel AECBOSMODE system variable has to be temporarily set only to connectors, and OSMODE to 0. Then (cadr (entsel)) returns coordinates of that connection point.

 

(vl-load-com)
(defun c:CONCOORD ( / obj1 tmpfpath1 list1 list2 list3 string1 infile1 elem1 i1)
    ;-----------------------------------------
    ;error section
    ;-----------------------------------------
    (defun *error* (msg) (princ "error: ") (princ msg) (princ) )
    (defun errtrap1 (errormsg1)
        (setq *error* temperr)
        (setvar "LUPREC" old_luprec)
        (command "_logfilepath" old_logfilepath)
        (command "_logfilemode" 0)
        (command-s "_UCS" "_NA" "_R" "old_ucs1"); restoring UCSr
        (command-s "_UCS" "_NA" "_D" "old_ucs1");deleting ucs name. "command" doesnt work within error trap. You have to use "command-s"
        (if (and errormsg1 (not (wcmatch (strcase errormsg1) "*BREAK*,*CANCEL*,*QUIT*") ) )
            (prompt (strcat "Error: " errormsg1) );then
        );if
        (princ) 
    );defun err
    ;-----------------------------------------
    ;setting variables
    ;-----------------------------------------
    (setq
        temperr *error* 
        *error* errtrap1 
        old_logfilepath (getvar "logfilepath")
        tmpfpath1 (strcat old_logfilepath "\\TEMP1DCL")
        old_luprec (getvar "LUPREC")
    );setq

    (vl-mkdir tmpfpath1)
    (setvar "LUPREC" 8)
    (command "_logfilepath" tmpfpath1)
    (command "_logfilemode" 1)
    (command "_UCS" "_NA" "_D" "old_ucs1")
    (command "_UCS" "_NA" "_S" "old_ucs1");naming current UCS
    (command "_ucs" "_w")
    ;-----------------------------------------
    ;object selection and reading of logfile
    ;-----------------------------------------
    (setq obj1 (car (CNO_OBJ_SELECTION)))
    (command "List" obj1 "")
    (command "_logfilemode" 0)
    (graphscr)
    (setq list2 (list) )
    (setq infile1 (open (getvar "LogFileName") "r"))
    (while (setq string1 (read-line infile1) )
        (if (not (null string1))
            (setq list1 (append list1 (list string1) ) );makes a list of strings of every line of this file
        ) ; if
    ) ;while
    (close infile1)
    ;-----------------------------------------
    ;creating list of points (STRING type)
    ;-----------------------------------------
    (foreach elem1 list1
        (if (= "  Connection Point : " (substr elem1  1 21 ) );21 letters in this string
            (progn
                (setq elem1 (substr elem1  23 (- (strlen elem1) 23) ) );removes spaces 
                (repeat 2 (setq elem1 (vl-string-subst "" " " elem1)))
                (setq list2 (cons elem1 list2 ) )
            );progn
        );if
    );foreach
    ;-----------------------------------------
    ;creating list of points
    ;-----------------------------------------
    (setq i1 1   list3 (list) )
    (repeat (length list2)
        (setq list3 (cons (COORD_TRANSF (nth (- i1 1) list2)  ) list3 ) )
        (setq i1 (1+ i1))
    );repeat
    ;-----------------------------------------
    ;restoring systemvariables
    ;-----------------------------------------
    (vl-file-delete (strcat tmpfpath1 "\\" (caddr (vl-directory-files tmpfpath1))  ) );deleting log file
    (setvar "LUPREC" old_luprec)
    (command "_logfilepath" old_logfilepath)
    (command "_UCS" "_NA" "_R" "old_ucs1");restoring UCS
    (command "_UCS" "_NA" "_D" "old_ucs1");deleting ucs name.
    (terpri)

    list3
);defun
;;; =================================================
;;;                          HELP FUNCTIONS
;;; =================================================
(defun COORD_TRANSF (str1 / gvar1 poz1 xcoord )
    (setq poz1 (vl-string-position (ascii ",") str1))
    ;(setq poz2 (vl-string-position (ascii ",") (vl-list->string (reverse (vl-string->list str1)))))
    (setq xcoord (atof (substr str1 1 poz1 ) ))
    (setq str1 (substr str1 (+ poz1 2) (strlen str1) ) )
    (setq poz1 (vl-string-position (ascii ",") str1))
    (setq gvar1 
        (list
            xcoord
            (atof (substr str1 1 poz1 ) )
            (atof (substr str1 (+ poz1 2) (strlen str1)))
        );list
    );setq
    gvar1
);defun

(defun CNO_OBJ_SELECTION ( / item1 iType)
    (setq item1 nil)
    (while (= item1 nil)
        (setq item1 (entsel "\nSelect duct / pipe / cabeltray  or fitting: \n")
                iType (cdr (assoc 0 (entget (car item1) ) ) )
        );setq
        (if (/= item1 nil)
        	(progn
                (if
                    (not
                        (or  
                            ;(= iType "AECB_PIPE")
                            ;(= iType "AECB_DUCT")
                            ;(= iType "AECB_CABLETRAY")
                            (= iType "AECB_PIPEFITTING")
                            (= iType "AECB_DUCTFITTING")
                            (= iType "AECB_CABLETRAYFITTING")
                        );or
                    );not
                    (progn ;then
                        (prompt "\nWrong object")
                        (setq item1 nil)
                    );progn
                );if
            );progn 
        );if
    );while
    item1
);defun

 


• www.autolisps.blogspot.com - Productivity plugins for Autocad and Autocad MEP
• Autodesk AppStore
0 Likes
Message 6 of 12

devitg
Advisor
Advisor

It is the famous proverb: KISS  , Keep It Simple Sir.

 

 

 

 

0 Likes
Message 7 of 12

CWagnerLYWJP
Participant
Participant

Trying to utilize your script and i'm running into an issue. I assume I'll run into a few issues as I am not all too familiar with lisp. To give you an idea of why i'm trying to use this. We have pipe that take special clamps at each point of connection. We did not model in the clamps and now have the issue of needing a count of how many clamps we need. So, I figure I can count the nodes of each fitting/pipe and provide a count that way, however, for shared nodes the count would reduce to 1 at that connection. I hope that is coherent enough to get some bit of help.

 

Here is the issue I have showing now when attempting to use your script:

 

Command: CONCOORD
_logfilepath
Enter new value for LOGFILEPATH, or . for none <"C:\Users\cwagner\appdata\local\autodesk\autocad 2020\r23.1\e...">: C:\Users\cwagner\appdata\local\autodesk\autocad 2020\r23.1\enu\\TEMP1DCL
Cannot set LOGFILEPATH to that value.

Cannot invoke (command) from *error* without prior call to (*push-error-using-command*).
Converting (command) calls to (command-s) is recommended.*Invalid*

0 Likes
Message 8 of 12

andkal
Collaborator
Collaborator

Hi
This routine I posted above is an old version. Below is newer with some bugs fixed. Anyway, this routine is for Autocad MEP. Basing on the error you got you are using classic Autocad

 

 

;;; =================================================
;;;        CONNECTOR_COORDINATES_AMEP_v1_03.LSP
;;;
;;;        Written by Andrzej Kalinowski,     www.autolisps.blogspot.com
;;;        v1.00 - 28.10.2017
;;;        v1.03 - 15.04.2019
;;;
;;;        Command: CONCOORD
;;;              This utility retrieves coordinates of all connectors of selected autocad meps
;;;              pipefitting, ductfitting or cabeltrayfitting which aren't normally available for visual lisp.
;;;              Coordinates of normal ducts and pipes are available in properties as start and end point.
;;;              Works in english, german and french Autocad only
;;;
;;; =================================================
(vl-load-com)
(defun c:CONCOORD ( / obj1 tmpfpath1 list1 list2 list3 str1 str2 infile1 elem1 i1 string1)
    ;-----------------------------------------
    ;error section
    ;-----------------------------------------
    (defun *error* (msg) (princ "error: ") (princ msg) (princ) )
    (defun errtrap1 (errormsg1)
        (princ "\n---------------------error---------------------") (terpri)
        (setq *error* temperr)
        (setvar "LUPREC" old_luprec)
        (setvar "LOGFILEPATH" old_logfilepath)
        (setvar "LOGFILEMODE" old_logfilemode)
        (if (and errormsg1 (not (wcmatch (strcase errormsg1) "*BREAK*,*CANCEL*,*QUIT*") ) )
            (prompt (strcat "\nError: " errormsg1) );then
        );if
        (princ) 
    );defun err
    ;-----------------------------------------
    ;setting variables
    ;-----------------------------------------
    (setq
        temperr *error* 
        *error* errtrap1 
        old_logfilepath (getvar "logfilepath")
        tmpfpath1 (strcat (getvar "MYDOCUMENTSPREFIX") "\\TEMP1DCL")
        old_luprec (getvar "LUPREC")
        old_logfilemode (getvar "LOGFILEMODE")
    );setq

    (vl-mkdir tmpfpath1)
    (setvar "LUPREC" 8); precision for linear units and coordinates (0-8)
    (setvar "logfilepath" tmpfpath1)
    ;-----------------------------------------
    ;object selection and reading of logfile
    ;-----------------------------------------
    (setq obj1 (car (CNO_OBJ_SELECTION)))
    (setvar "LOGFILEMODE" 1)
    (command "_List" obj1 "");turns on textscr
    (setvar "LOGFILEMODE" 0)
    (command "_textscr");turns off textscr (toggle since 2014)
    (graphscr)
    (setq list2 (list) )
    (setq infile1 (open (getvar "LogFileName") "r"))
    (while (setq string1 (read-line infile1) )
        (if (not (null string1))
            (setq list1 (append list1 (list string1) ) );makes a list of strings of every line of this file
        ) ; if
    ) ;while
    (close infile1)

    ;-----------------------------------------
    ;creating list of points (STRING type)
    ;-----------------------------------------
    (foreach elem1 list1
        (if (or
                (/= nil (vl-string-search "Connection Point" elem1));EN
                (/= nil (vl-string-search "Point de connexion" elem1));FR
                (/= nil (vl-string-search "Verbindungspunkt" elem1));DE
            );or
            (progn
                (setq elem1 (substr elem1 (+ 2 (vl-string-position (ascii "(") elem1) ) (strlen elem1) ) )
                (setq elem1 (substr elem1 1 (- (strlen elem1) 1) ))
                (repeat 2 (setq elem1 (vl-string-subst "" " " elem1)));removes spaces,
                (setq list2 (cons elem1 list2 ) )
            );progn
        );if
    );foreach
    ;-----------------------------------------
    ;creating list of points
    ;-----------------------------------------
    (setq i1 1   list3 (list) )
    (foreach elem1 list2
        (setq list3 (cons (trans (COORD_TRANSF elem1) 1 0) list3) )
    );foreach
    ;-----------------------------------------
    ;restoring systemvariables
    ;-----------------------------------------
    (vl-file-delete (strcat tmpfpath1 "\\" (caddr (vl-directory-files tmpfpath1))  ) );deleting log file
    (setvar "LUPREC" old_luprec)
    (setvar "LOGFILEPATH" old_logfilepath)
    (setvar "LOGFILEMODE" old_logfilemode)
    (graphscr)
    list3
);defun
;;; =================================================
;;;                          HELP FUNCTIONS
;;; =================================================
(defun COORD_TRANSF (str1 / gvar1 poz1 xcoord );transforms XYZ coordinates stored as a string to a list of real numbers
    (setq poz1 (vl-string-position (ascii ",") str1))
    ;(setq poz2 (vl-string-position (ascii ",") (vl-list->string (reverse (vl-string->list str1)))))
    (setq xcoord (atof (substr str1 1 poz1 ) ))
    (setq str1 (substr str1 (+ poz1 2) (strlen str1) ) )
    (setq poz1 (vl-string-position (ascii ",") str1))
    (setq gvar1 
        (list
            xcoord
            (atof (substr str1 1 poz1 ) )
            (atof (substr str1 (+ poz1 2) (strlen str1)))
        );list
    );setq
    gvar1
);defun
;;; =================================================
;;;                          CNO_OBJ_SELECTION 
;;; =================================================
(defun CNO_OBJ_SELECTION ( / item1 iType)
    (setq item1 nil)
    (while (= item1 nil)
        (setq item1 (entsel "\nSelect duct / pipe / cabeltray  or fitting: \n")
                iType (cdr (assoc 0 (entget (car item1) ) ) )
        );setq
        (if (/= item1 nil)
        	(progn
                (if
                    (not
                        (or  
                            ;(= iType "AECB_PIPE")
                            (= iType "AECB_DUCT")
                            ;(= iType "AECB_CABLETRAY")
                            ;(= iType "AECB_PIPEFITTING")
                            (= iType "AECB_DUCTFITTING")
                            (= iType "AECB_CABLETRAYFITTING")
                            ;(= iType "AECB_MVPART")
                        );or
                    );not
                    (progn ;then
                        (prompt "\nWrong object")
                        (setq item1 nil)
                    );progn
                );if
            );progn 
        );if
    );while
    item1
);defun

• www.autolisps.blogspot.com - Productivity plugins for Autocad and Autocad MEP
• Autodesk AppStore
0 Likes
Message 9 of 12

CWagnerLYWJP
Participant
Participant

We are using CADmep 2020 🙂

 

Thank you for the quick response! I'll see if I can use this to achieve what I need.

 

 

0 Likes
Message 10 of 12

CWagnerLYWJP
Participant
Participant

I'm getting this now:

 

Select duct / pipe / cabeltray or fitting:
Wrong object

 

Below is the object properties that I was able to gather using a script I found. One thing not shown is the CID which is "2041"

 

The endpoint data is what i'm looking for. I intend use that data to identify shared points for a total count of clamps that we will need for this type of pipe.

 

Command: HAVEADUMP
Select object:
; IMapsComWrap: IMapsComWrap Interface
; Property values:
; Application (RO) = #<VLA-OBJECT IAcadApplication 00007ff619731e30>
; Area = 0.621774
; CustomData = "Manufacturer = ,Model = ,Model Option 1 = ,Model Option 2 = ,Model Option 3 = ,Model Option 4 = ,Device Handing = ,Device Tag = ,Device ID = ,CFM / GPM = ,TYP. X = ,Room No = ,Weld Inches = ,Fabrication Time = ,Asset ID = ,"
; Description = "Blucher Pipe - SS-316 [ 2\" ]"
; Document (RO) = #<VLA-OBJECT IAcadDocument 0000019fa7175bb8>
; Elevation = "BOP/I: 13'-10 3/16\""
; EndSize = "Straight 2, Socket 2, "
; EntityTransparency = "ByLayer"
; Handle (RO) = "246E1"
; HasExtensionDictionary (RO) = 0
; Hyperlinks (RO) = #<VLA-OBJECT IAcadHyperlinks 0000019fa1697868>
; ItemNumber = "3380"
; ItemServiceType = "Pipework"
; ItemSpoolName = ""
; Layer = "P-WV_N_PIPE_W"
; LengthAngle = 100.506
; Linetype = "ByLayer"
; LinetypeScale = 1.0
; Lineweight = -1
; Material = "ByLayer"
; Notes = ""
; ObjectID (RO) = 44
; ObjectName (RO) = "MapsContainer"
; OwnerID (RO) = 43
; PlotStyleName = "ByLayer"
; Points = "ENDPOINTS: 1260.76,802.77,167.39;1361.24,802.77,169.48;"
; Section = "None"
; ServiceName = "W (AG - Blucher SS-316)"
; Status = " 0: Design"
; TrueColor = #<VLA-OBJECT IAcadAcCmColor 0000019fa16975c0>
; Visible = -1
; Weight = 0.0
; Methods supported:
; ArrayPolar (3)
; ArrayRectangular (6)
; Copy ()
; Delete ()
; GetBoundingBox (2)
; GetExtensionDictionary ()
; GetXData (3)
; Highlight (1)
; IntersectWith (2)
; Mirror (2)
; Mirror3D (3)
; Move (2)
; Rotate (2)
; Rotate3D (3)
; ScaleEntity (2)

0 Likes
Message 11 of 12

andkal
Collaborator
Collaborator

The list you provided says "; ObjectName (RO) = "MapsContainer"".
Lisp routine I posted works with fittings made in Autocad MEP (object type: aecb_ductfitting). It wont work for your object. I assume your object was created in some third party plugin installed on Autocad MEP.

Try to display what is under group code 10. for this entity (use f.e.  http://autolisps.blogspot.com/p/disprop.html)
10. is a primary point, but not all object types have that property. Primary point may also not necessarily be an end point which you are looking for.
Im not sure if autolisp will help you.


• www.autolisps.blogspot.com - Productivity plugins for Autocad and Autocad MEP
• Autodesk AppStore
0 Likes
Message 12 of 12

CWagnerLYWJP
Participant
Participant

I assume there is a way to use the data using that script but for everything that I have selected and some how parse the Endpoint data into a list, eliminate shared points, and then use the list length to give me the point count right?

 

My issue atm is Im trying to learn these things inbetween tasks haha.

0 Likes