I know there must be a way to extract custom Xdata from an Autocad drawing.
Could somebody please point me in the right direction of where to search?
I'm looking for a method or AutoLISP that will collect/extract the custom added, Xdata from a bunch of polylines. These polylines will have the following custom Xdata;
The standard 'Extract Data' method in Autocad does not extract any name or another reference to the extracted data. So there is no way telling which data is from which polyline.
Any help would be greatly appreciated.
To obtain xdata associated with a particular Application ID or multiple Application IDs, simply supply the entget function with the optional applist
argument following the entity name argument.
This argument is a list of Application IDs for which to return xdata (if present in the DXF data associated with the supplied entity).
For example, if your Application ID is "MyAppID"
, you would evaluate the entget
function in the following manner:
(entget <entity-name> '("MYAPPID"))
(Note that I have supplied a quoted literal list in this example - for more information on this convention, refer to my tutorial on the subject).
To help you to inspect all DXF data (including xdata) associated with a particular entity, I have developed an Entity List program.
On selecting a polyline from your drawing using this program or by evaluating entget
with an application list argument of ("MYAPPID")
, you may obtain a DXF data such as:
(
(-1 . <Entity name: 7ffff706880>) ;; Pointer to self
(0 . "LWPOLYLINE") ;; Entity Type
(330 . <Entity name: 7ffff7039f0>) ;; Point to parent
(5 . "FFF") ;; Handle
(100 . "AcDbEntity") ;; Class
(67 . 0) ;; Tilemode
(410 . "Model") ;; Layout
(8 . "0") ;; Layer
(100 . "AcDbPolyline") ;; Subclass
(90 . 4) ;; Vertices
(70 . 1) ;; Bitwise flag (1=Closed)
(43 . 0.0) ;; Constant width
(38 . 0.0) ;; Elevation
(39 . 0.0) ;; Thickness
(10 18.9133 17.6315) ;; Vertex coordinate (OCS)
< ... additional vertex data ... >
(10 18.9133 12.7863) ;; Vertex coordinate (OCS)
(40 . 0.0) ;; Segment starting width
(41 . 0.0) ;; Segment ending width
(42 . 0.0) ;; Segment bulge
(91 . 0) ;; Vertex identifier
(210 0.0 0.0 1.0) ;; Extrusion (normal) vector
;; xData starts here:
(-3
(
"MYAPPID" ;; Application ID
(1002 . "{") ;; Data grouping opening brace
(1040 . 1.2345) ;; Real-valued (Double) data (your area value)
(1070 . 123) ;; Int-valued data (your polyline number)
(1000 . "MyPolyline") ;; String-valued data (your polyline name)
(1002 . "}") ;; Data grouping closing brace
)
)
)
Therefore, the list of xdata may be accessed by acquiring DXF group -3 from this list:
(assoc -3 (entget <entity-name> '("MYAPPID")))
Which will return:
(-3
(
"MYAPPID" ;; Application ID
(1002 . "{") ;; Data grouping opening brace
(1040 . 1.2345) ;; Real-valued (Double) data (your area value)
(1070 . 123) ;; Int-valued data (your polyline number)
(1000 . "MyPolyline") ;; String-valued data (your polyline name)
(1002 . "}") ;; Data grouping closing brace
)
)
If you are querying more than one Application ID, you may then acquire the data associated with your target Application ID using:
(cdr (assoc "MYAPPID" (cdr (assoc -3 (entget <entity-name> '("MYAPPID"))))))
Or, if you are only returning the xdata associated with one Application ID, you could simply use:
(cdadr (assoc -3 (entget <entity-name> '("MYAPPID"))))
Here, cdadr
is a contraction of (cdr (car (cdr)))
.
This will then return:
(
(1002 . "{") ;; Data grouping opening brace
(1040 . 1.2345) ;; Real-valued (Double) data (your area value)
(1070 . 123) ;; Int-valued data (your polyline number)
(1000 . "MyPolyline") ;; String-valued data (your polyline name)
(1002 . "}") ;; Data grouping closing brace
)
From which you may retrieve the relevant values either using assoc
if the group codes are unique, or iterate over the list and rely on the association pair positioning.
Here is a test program for you to try:
(defun c:test ( / ent )
(if (setq ent (car (entsel)))
(print (cdadr (assoc -3 (entget ent '("MYAPPID")))))
)
(princ)
)