PDA

View Full Version : Searching for C3D surfaces within drawings



gstankus341551
2012-07-30, 09:01 PM
Does anyone know of a way to search for c3d surfaces within drawings? I have a list of drawings that would have had their surfaces promoted and I would like to catalog which files contain:
1)what surfaces are within that drawing
2)what surfaces are referenced within that drawing.

I thought there was a way to search for that data, but I cannot find anything to do this. The data shortcuts editor simply tells you what references are in a particular location. The xref manager wont work as it wont recognize surfaces.

Any ideas?

Using c3d 2012.....

Thank you,

G-

BlackBox
2012-07-30, 11:48 PM
I am no Civil 3D expert, but this simple LISP should allow you to use either a Script (SCR), or an ObjectDBX wrapper to iterate a directory of drawings, to determine which drawings contain Surface(s).

Should you so choose, you can also iterate the list of Surfaces returned to programmatically modify each Surface (i.e., Layer, StyleName, etc.):



(vl-load-com)

(defun C3d-Get-Surfaces (oDoc / objectName surfaces)
;; RenderMan, 2012, AUGI.com
;; Example: (if (C3d-Get-Surfaces acDoc) T nil)
;; Return: (# <list>)
(vlax-for x (vla-get-block (vla-get-layout (vla-get-modelspace oDoc)))
(if (and (wcmatch
(setq objectName (vla-get-objectname x))
"AeccDbSurface*"
)
(not (vl-string-search "Label" objectName))
)
(setq surfaces (cons x surfaces))
)
)
(if surfaces
(cons (length surfaces) (reverse surfaces))
)
)


HTH

Opie
2012-07-31, 04:28 PM
I am no Civil 3D expert, but this simple LISP should allow you to use either a Script (SCR), or an ObjectDBX wrapper to iterate a directory of drawings, to determine which drawings contain Surface(s).

Should you so choose, you can also iterate the list of Surfaces returned to programmatically modify each Surface (i.e., Layer, StyleName, etc.):



(vl-load-com)

(defun C3d-Get-Surfaces (oDoc / surfaces)
;; RenderMan, 2012, AUGI.com
;; Example:
;; (if (C3d-Get-Surfaces acDoc) T nil)
(vlax-for x (vla-get-block (vla-get-layout (vla-get-modelspace oDoc)))
(if (wcmatch (vla-get-objectname x) "AeccDbSurface*")
(setq surfaces (cons x surfaces))
)
)
(if surfaces
(cons (length surfaces) (reverse surfaces))
)
)


HTH

Hey Renderman,

Your code also pulls in surface labels that are in the drawing. You might modify your condition in your first if function to make sure "*Label*" is not within the objectname. I would code it up, but I am pretty sure you already know how. :p

BlackBox
2012-07-31, 04:36 PM
Hey Renderman,

Your code also pulls in surface labels that are in the drawing. You might modify your condition in your first if function to make sure "*Label*" is not within the objectname. I would code it up, but I am pretty sure you already know how. :p

Good catch, code revised.

Opie
2012-07-31, 04:49 PM
I only caught it because I tried your code on an existing labeled surface.

BlackBox
2012-07-31, 04:51 PM
I only caught it because I tried your code on an existing labeled surface.

No... I meant good for me, not you. :p

Seriously though, thanks for trying the code, Opie - I hope you find it to be useful! :beer:

gstankus341551
2012-07-31, 05:43 PM
OK- I am no VL King or any kind of King, and this code has gone completely over my head. Do I load it as a lisp, i.e save it out as .lsp and appload it? Run the VB command prompt, or the VLisp console window? Save it as an .scr and run it that way? I am familiar with lisp - very basic autolisp, beyond that and I am lost. Scripts and VB are things that I would like to learn but have not.

What I am in need of, I have a drawing that has a broken surface reference. We have a directory of older files that are archived files that have been sent to the client, where all the xref's and surfaces were bound/promoted into each individual dwg file that was sent. I need a way to search the directory of dwg files for that old and outdated surface that is being requested. I would like and easy way to look at approx 150 drawings and see what surfaces are within those cad files.

Thank you,

G-

BlackBox
2012-07-31, 06:02 PM
OK- I am no VL King or any kind of King, and this code has gone completely over my head.


No worries; neither am I. LoL



Do I load it as a lisp, i.e save it out as .lsp and appload it? Run the VB command prompt, or the VLisp console window? Save it as an .scr and run it that way? I am familiar with lisp - very basic autolisp, beyond that and I am lost. Scripts and VB are things that I would like to learn but have not.

Having read the latter part of your last post, don't worry about trying out the sub-function above... See below.



What I am in need of, I have a drawing that has a broken surface reference. We have a directory of older files that are archived files that have been sent to the client, where all the xref's and surfaces were bound/promoted into each individual dwg file that was sent. I need a way to search the directory of dwg files for that old and outdated surface that is being requested. I would like and easy way to look at approx 150 drawings and see what surfaces are within those cad files.


Now _that_ sounds like a fun request (I'm totally rocking out with my geek out, right now, I know)...!

Let me wrap some stuff up, and I'll see what I can throw together. I'll also include some clarification to the questions you asked above.

BlackBox
2012-07-31, 09:29 PM
I'm pretty happy with how this turned out, for such little time spent.

The BatchFindSurface Command prompts the user to specify a directory to search, and if drawings are found, proceeds to open each drawing programmatically using ObjectDBX, searching ModelSpace for Surfaces, and writing each Surface's data to file. If Surfaces are found, the file is opened, otherwise a message is displayed at the command line.



(vl-load-com)

(defun c:BFindSurf () (c:BatchFindSurface))
(defun c:BatchFindSurface
(/ *error*
C3d-Get-Surfaces
RM:GetDate RM:GetTime
RM:WriteData
)
;; RenderMan, 2012, AUGI.com
(princ "\rBATCHFINDSURFACE ")

(defun *error* (msg)
(if file
(close file)
)
(if oShell
(vlax-release-object oShell)
)
(if dbxDoc
(vlax-release-object dbxDoc)
)
(cond ((not msg)) ; Normal exit
((member msg '("Function cancelled" "quit / exit abort"))) ; <esc> or (quit)
((princ (strcat "\n** Error: " msg " ** ")))
) ; Fatal error, display it
(princ)
)

(defun C3d-Get-Surfaces (oDoc / objectName surfaces)
(vlax-for x (vla-get-block
(vla-get-layout (vla-get-modelspace oDoc))
)
(if (and (wcmatch
(setq objectName (vla-get-objectname x))
"AeccDbSurface*"
)
(not (vl-string-search "Label" objectName))
(= 0 (vlax-invoke x 'isreferenceobject))
)
(setq surfaces (cons x surfaces))
)
)
(if surfaces
(cons (length surfaces) (reverse surfaces))
)
)

(defun RM:GetDate (date)
(setq date (mapcar '(lambda (x) (itoa x)) date))
(strcat (nth 0 date) "-" (nth 1 date) "-" (nth 3 date))
)

(defun RM:GetTime (date / hr mn)
(setq hr (nth 4 date))
(setq mn (itoa (nth 5 date)))
(if (= 1 (strlen mn))
(setq mn (strcat "0" mn))
)
(cond ((> 12 hr) (strcat (itoa hr) ":" mn " AM"))
((strcat (itoa (- hr 12)) ":" mn " PM"))
)
)

(defun RM:WriteData (dbxDoc file surface / path date)
(write-line
(vl-string-right-trim
","
(apply
'strcat
(mapcar
'(lambda (x) (strcat x ","))
(list (setq path (vla-get-name dbxDoc))
(RM:GetDate (setq date (vl-file-systime path)))
(RM:GetTime date)
(vla-get-name surface)
(vla-get-description surface)
(vla-get-handle surface)
(vla-get-layer surface)
(vla-get-stylename surface)
(vla-get-objectname surface)
)
)
)
)
file
)
)

((lambda (acApp dwgName / oShell oFolder path
dwgs filePath dbxDoc file surfaces ok
)
(if (and (setq oShell
(vla-getinterfaceobject acApp "Shell.Application")
)
(setq oFolder
(vlax-invoke
oShell
'BrowseForFolder
(vla-get-hwnd acApp)
"Select folder to search:"
0
(+ 1 64 256)
)
)
(setq path (vlax-get-property
(vlax-get-property oFolder 'Self)
'Path
)
)
(setq dwgs (vl-directory-files path "*.dwg" 1))
(setq filePath
(strcat
(vl-filename-directory (vl-filename-mktemp))
"\\Batch Find Surface Report_"
(menucmd "M=$(edtime,$(getvar,date),YYYY-MO-DD)")
".csv"
)
)
(princ "\nWorking, please wait...")
(princ)
(setq dbxDoc (vla-getinterfaceobject
acApp
(strcat "ObjectDBX.AxDbDocument."
(substr (getvar 'acadver) 1 2)
)
)
)
)
(progn
(setq file (open filePath "w"))
(write-line "Directory Searched:" file)
(write-line path file)
(write-line "" file)
(write-line
"Drawing:,Date:,Time:,Surface:,Description:,Handle:,Layer:,Style:,Type:"
file
)
(foreach dwg dwgs
(if (/= dwg dwgName)
(progn
(vl-catch-all-apply
'vla-open
(list dbxDoc (strcat path "\\" dwg))
)
(if (setq surfaces (C3d-Get-Surfaces dbxDoc))
(progn
(or ok (setq ok T))
(foreach surface (cdr surfaces)
(RM:WriteData dbxDoc file surface)
)
)
)
)
)
)
(princ "Done.")
(setq file (close file))
(if ok
(vlax-invoke oShell 'open filePath)
(prompt "\n** No surfaces found ** ")
)
(*error* nil)
)
(cond
(file
(*error*
"Unable to create \"ObjectDBX.AxDbDocument\" Object"
)
)
(oFolder (*error* "No drawings found"))
(oShell (*error* "No folder selected"))
(fso
(*error* "Unable to create \"Shell.Application\" Object")
)
((*error*
"Unable to create \"Scripting.FileSystemObject\" Object"
)
)
)
)
)
(vlax-get-acad-object)
(getvar 'dwgname)
)
)


To use this LISP routine, see Lee's excellent tutorial here (http://www.lee-mac.com/runlisp.html).

Once you've tried the routine, please let me know how this works for you, cheers! :beer:

gstankus341551
2012-08-01, 05:56 PM
Now _that_ sounds like a fun request (I'm totally rocking out with my geek out, right now, I know)...!

LOL!

Thanks for your help - it works great for what seems to be smaller directories of files (<10 dwg files) as it crashed the system on another folder that had around 25 files within it.

BUT, this is EXACTLY what I was hoping to find - a list of the drawing file name and a listing of surfaces contained within those files. Now where is that wish list for future improvements to c3d.....

Thank you, Thank you,

G-

BlackBox
2012-08-01, 06:36 PM
Thanks for your help - it works great for what seems to be smaller directories of files (<10 dwg files) as it crashed the system on another folder that had around 25 files within it.

BUT, this is EXACTLY what I was hoping to find - a list of the drawing file name and a listing of surfaces contained within those files. Now where is that wish list for future improvements to c3d.....


Hrrrmm.... I wonder what's causing you to crash? It's possible I've missed something, given how long it's been since I coded ObjectDBX, but I doubt it, as I just tested it on each, a directory of 30 drawings (+/-20 sec), 75 drawings (+/- 45 sec), and then 138 drawings (+/-1.5 min) respectively, with no crash.

In any event, I'm glad you're finding it to be at least somewhat useful. :beer:

FWIW -

I plan to incorporate some optional recursive search functionality using the Scripting.FileSystemObject (http://msdn.microsoft.com/en-us/library/6kxy1a51%28VS.85%29.aspx) Object, based on the user-specified directory. Another task for another day, I am afraid.

While I'm at it, I should go ahead an enabled the other 'major' Civil 3D Objects as optional items for query as well... I already have LISP sub-functions for C3d-Get-[CogoPoints, PointClouds, Surfaces, SurfaceRefs, Alignments, AlignmentRefs, Profiles, ProfileRefs, ProfileViews, Sites, Parcels, PipeNetworks, PipeNetworkRefs, Corridors, Subassemblies, Intersections, and all DataRefs], so it shouldn't be too hard.

Cheers! :beer:

gstankus341551
2012-08-02, 03:46 PM
At the end of the day yesterday - I was getting it to run on around 300+ drawings without a crash. More than that and it began to eat up my memory and crash. I think it also had something to do with a few of the files needing recovery or some other error when your script was going through them.

Thanks again, this helped tremendously!

G-

BlackBox
2012-08-02, 04:11 PM
Thanks again, this helped tremendously!


You're welcome; happy to help. :beer: