Jump to content

Finding Local Depressions in Surface


broncos15

Recommended Posts

I am trying to write a routine that would draw polylines to all the local depressions in a surface. The way that I currently find the local depressions is by doing a watershed analysis, changing my surface style to show local depressions as node points, and then just manually going around and verifying that the local depressions are correct. On very large sites (20+ acres) it is time consuming to go make sure that you didn't miss any local depressions when you go through and check each one.

 

 

That is why I want to have a routine that would let me select the surface after a watershed analysis is performed and draw polylines to every local depression node. The issue is that I cannot find where that information is stored. I have done a dump of the vla information and dxf information and cannot find anything. Does anyone have any suggestions?

Link to comment
Share on other sites

  • Replies 22
  • Created
  • Last Reply

Top Posters In This Topic

  • broncos15

    11

  • ronjonp

    10

  • BIGAL

    1

  • lrm

    1

Top Posters In This Topic

Sounds like a fun problem. Can you post your file? ( you'll have to bear with me though, I'm fairly C3D illiterate :) )

Link to comment
Share on other sites

Thank you so much for being able to look at this! This is just a really quick example.

 

No knowing exactly what you're trying to accomplish from the example drawing, maybe this will give you a start. It draws a line from a picked point to all drain locations ( which I assume are depressions? )

(defun c:sa (/ _getsurfaceanalysis a anlsys drains out p p2 wshed x)
 ;; https://www.theswamp.org/index.php?topic=50877.msg559985#msg559985
 ;; RJP modified for surface analysis 07.07.2017
 (defun _getsurfaceanalysis (/ c3d civdb civdoc out)
   (if	(and (setq c3d (strcat "HKEY_LOCAL_MACHINE\\"
		       (if vlax-user-product-key
			 (vlax-user-product-key)
			 (vlax-product-key)
		       )
	       )
     )
     (setq c3d (vl-registry-read c3d "Release"))
     (setq c3d (substr c3d 1 (vl-string-search "." c3d (+ (vl-string-search "." c3d) 1))))
     (setq c3d (vla-getinterfaceobject
		 (vlax-get-acad-object)
		 (strcat "AeccXUiLand.AeccApplication." c3d)
	       )
     )
     (setq civdoc (vlax-get c3d 'activedocument))
     (setq civdb (vlax-get civdoc 'database))
)
     (vlax-for x (vlax-get civdb 'surfaces) (setq out (cons (vlax-get x 'surfaceanalysis) out)))
   )
   out
 )
 (if (and (setq a (_getsurfaceanalysis))
   (setq anlsys (mapcar '(lambda (x) (vlax-get x 'watershedanalysis)) a))
   (setq wshed (mapcar '(lambda (x) (vlax-get x 'watershedregions)) anlsys))
   (or (foreach	shed wshed
	 (vlax-for shed2 shed
	   (if (vlax-property-available-p shed2 'drains)
	     (setq drains (cons (vlax-get shed2 'drains) drains))
	   )
	 )
       )
       drains
   )
   (foreach drain drains (vlax-for drain2 drain (setq out (cons drain2 out))))
   (setq p (getpoint "\nPick a point away from the surface: "))
     )
   (foreach x out
     (if (setq p2 (vlax-get x 'location))
(entmakex (list '(0 . "line") (cons 10 p) (cons 11 p2)))
     )
   )
 )
 (princ)
)

Edited by ronjonp
Link to comment
Share on other sites

Nice one Ronjop once you know what your looking for in terms of database names you can get a lot of info as per the link. I have the Version check as a Library defun, I use the check in a number of surface routines. Getting the info via the registery is a good idea.

 

For any one using the other ways of finding the version numbers.

 

((vl-string-search "R20.0" vrsn)(setq appstr "10.4"));;2015
        ((vl-string-search "R20.1" vrsn)(setq appstr "10.5"));;2016     
        ((vl-string-search "R21.0" vrsn)(setq appstr "11.0"));;2017   
        ((vl-string-search "R22.0" vrsn)(setq appstr "12.0"));;2018

 

You may be interested in this

Chcontourstoolbar.zip

Edited by BIGAL
Link to comment
Share on other sites

Ron, thank you so much for the help with this! When I try running the function, I get the following error: ActiveX Server returned the error: unknown name: "DRAINS". I know that this means that the function drains doesn't exist, but what should I replace that with?

Link to comment
Share on other sites

Ron, thank you so much for the help with this! When I try running the function, I get the following error: ActiveX Server returned the error: unknown name: "DRAINS". I know that this means that the function drains doesn't exist, but what should I replace that with?

The error is probably on this line:

(vlax-for shed2 shed (setq drains (cons [b](vlax-get shed2 'drains)[/b] drains)))

You're going to have to troubleshoot this as the code works on my computer, but I'm also using C3D 2017.

Link to comment
Share on other sites

Ah, that makes sense. I am using 2015, so I will have to see if this function exists for 2015, or if there is an equivalent function.

Link to comment
Share on other sites

So I have been looking through the developer’s guide for 2013 and 2015 and it states “The .NET API does not implement an equivalent to the COM API AeccSurfaceAnalysisWatershed.CalculateWatersheds() method, but you can use the SurfaceAnalysis.Ge****ershedData() method to access watershed

data from an existing analysis, and change properties (such as AreaColor) of watershed regions.” After running through each line of code, the anlsys variable (which finds the watershed analysis) and the wshed, which finds the watershedregions, both give valid responses. I’m confused why they won’t give the drains value (for a local depression) after looking through the developer’s guide.

 

Does anyone have any suggestions/advice on what I can try to look into?

Link to comment
Share on other sites

Can you post the drawing you're trying the code out on?

 

Here's an object dump on: IAeccWatershedRegionDepression

 

; IAeccWatershedRegionDepression: Watershed Region Depression interface

; Property values:

; Area (RO) = 80.0

; BoundaryLine (RO) = multi dimension safearray not supported

; Drains (RO) = #

; Id (RO) = 1

; Type (RO) = 2

; No methods

Edited by ronjonp
Link to comment
Share on other sites

I updated the original code. The reason it was erroring out is because there are different types of objects embedded within the 'wshed'.

_$

(#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

#

)

Link to comment
Share on other sites

That works nearly perfectly, thank you so much for your help! The lines are being drawn to the lowest the lowest points on the depressions region edge where this overflow may take place, rather than the actual lowest point within the watershed depression (i.e. the local depression). I am going to try and see if I can figure out where that information is located within the watershed depression.

Link to comment
Share on other sites

I don't see anything within 'wsched' objects that will draw lines to the red drains on your last example drawing. Here's another version that does a bit more .. maybe you can figure out what you need :)

(defun c:sa (/ _getsurfaceanalysis a anlsys drains drainpt out p p2 wshed x)
 ;; https://www.theswamp.org/index.php?topic=50877.msg559985#msg559985
 ;; RJP modified for surface analysis 07.07.2017
 (defun _getsurfaceanalysis (/ c3d civdb civdoc out)
   (if	(and (setq c3d (strcat "HKEY_LOCAL_MACHINE\\"
		       (if vlax-user-product-key
			 (vlax-user-product-key)
			 (vlax-product-key)
		       )
	       )
     )
     (setq c3d (vl-registry-read c3d "Release"))
     (setq c3d (substr c3d 1 (vl-string-search "." c3d (+ (vl-string-search "." c3d) 1))))
     (setq c3d (vla-getinterfaceobject
		 (vlax-get-acad-object)
		 (strcat "AeccXUiLand.AeccApplication." c3d)
	       )
     )
     (setq civdoc (vlax-get c3d 'activedocument))
     (setq civdb (vlax-get civdoc 'database))
)
     (vlax-for x (vlax-get civdb 'surfaces) (setq out (cons (vlax-get x 'surfaceanalysis) out)))
   )
   out
 )
 (if (and (setq a (_getsurfaceanalysis))
   (setq anlsys (mapcar '(lambda (x) (vlax-get x 'watershedanalysis)) a))
   (setq wshed (mapcar '(lambda (x) (vlax-get x 'watershedregions)) anlsys))
   (or (foreach	shed wshed
	 (vlax-for shed2 shed
	   (cond ((vlax-property-available-p shed2 'drains)
		  (setq drains (cons (vlax-get shed2 'drains) drains))
		 )
		 ((vlax-property-available-p shed2 'drainpoint)
		  (setq drainpt (cons (vlax-get shed2 'drainpoint) drainpt))
		 )
		 ((vlax-property-available-p shed2 'boundarydrainpoint)
		  (setq drainpt (cons (vlax-get shed2 'boundarydrainpoint) drainpt))
		 )
		 ((vlax-property-available-p shed2 'boundarydrainsegment)
		  (setq drainpt (cons (vlax-get shed2 'boundarydrainsegment) drainpt))
		 )
	   )
	 )
       )
       drains
   )
   (foreach drain drains
     (vlax-for drain2 drain (setq out (cons (vlax-get drain2 'location) out)))
   )
   (setq p (getpoint "\nPick a point away from the surface: "))
     )
   (foreach x (append out drainpt)
     (setq p2 x)
     (if (= 3 (length p2))
(entmakex (list '(0 . "line") (cons 10 p) (cons 11 p2)))
(while p2
  (entmakex (list '(0 . "line") (cons 10 p) (cons 11 (list (car p2) (cadr p2) (caddr p2)))))
  (setq p2 (cdddr p2))
)
     )
   )
 )
 (princ)
)

Link to comment
Share on other sites

I don't see anything within 'wsched' objects that will draw lines to the red drains on your last example drawing. Here's another version that does a bit more .. maybe you can figure out what you need :)

(defun c:sa (/ _getsurfaceanalysis a anlsys drains drainpt out p p2 wshed x)
 ;; https://www.theswamp.org/index.php?topic=50877.msg559985#msg559985
 ;; RJP modified for surface analysis 07.07.2017
 (defun _getsurfaceanalysis (/ c3d civdb civdoc out)
   (if    (and (setq c3d (strcat "HKEY_LOCAL_MACHINE\\"
                  (if vlax-user-product-key
                (vlax-user-product-key)
                (vlax-product-key)
                  )
              )
        )
        (setq c3d (vl-registry-read c3d "Release"))
        (setq c3d (substr c3d 1 (vl-string-search "." c3d (+ (vl-string-search "." c3d) 1))))
        (setq c3d (vla-getinterfaceobject
            (vlax-get-acad-object)
            (strcat "AeccXUiLand.AeccApplication." c3d)
              )
        )
        (setq civdoc (vlax-get c3d 'activedocument))
        (setq civdb (vlax-get civdoc 'database))
   )
     (vlax-for x (vlax-get civdb 'surfaces) (setq out (cons (vlax-get x 'surfaceanalysis) out)))
   )
   out
 )
 (if (and (setq a (_getsurfaceanalysis))
      (setq anlsys (mapcar '(lambda (x) (vlax-get x 'watershedanalysis)) a))
      (setq wshed (mapcar '(lambda (x) (vlax-get x 'watershedregions)) anlsys))
      (or (foreach    shed wshed
        (vlax-for shed2 shed
          (cond ((vlax-property-available-p shed2 'drains)
             (setq drains (cons (vlax-get shed2 'drains) drains))
            )
            ((vlax-property-available-p shed2 'drainpoint)
             (setq drainpt (cons (vlax-get shed2 'drainpoint) drainpt))
            )
            ((vlax-property-available-p shed2 'boundarydrainpoint)
             (setq drainpt (cons (vlax-get shed2 'boundarydrainpoint) drainpt))
            )
            ((vlax-property-available-p shed2 'boundarydrainsegment)
             (setq drainpt (cons (vlax-get shed2 'boundarydrainsegment) drainpt))
            )
          )
        )
          )
          drains
      )
      (foreach drain drains
        (vlax-for drain2 drain (setq out (cons (vlax-get drain2 'location) out)))
      )
      (setq p (getpoint "\nPick a point away from the surface: "))
     )
   (foreach x (append out drainpt)
     (setq p2 x)
     (if (= 3 (length p2))
   (entmakex (list '(0 . "line") (cons 10 p) (cons 11 p2)))
   (while p2
     (entmakex (list '(0 . "line") (cons 10 p) (cons 11 (list (car p2) (cadr p2) (caddr p2)))))
     (setq p2 (cdddr p2))
   )
     )
   )
 )
 (princ)
)

I will mess around with this updated code and see what I can do. Thank you again for all of your help!
Link to comment
Share on other sites

So I think I figured out how to get the point, it will be the centroid of the boundary line of the watershed region. The point values of the boundary lines are in an array, which I am not very good at. I have tried to mess with code and do

(foreach shed wshed
  (vlax-for shed2 shed
    (if (vlax-property-available-p shed2 'boundaryline)
      (setq drains (cons (vlax-SafeArray->List (vlax-get-property  shed2 'boundaryline)) drains))
    )
  )
       )

Link to comment
Share on other sites

So I think I figured out how to get the point, it will be the centroid of the boundary line of the watershed region. The point values of the boundary lines are in an array, which I am not very good at. I have tried to mess with code and do
(foreach shed wshed
  (vlax-for shed2 shed
    (if (vlax-property-available-p shed2 'boundaryline)
      (setq drains (cons (vlax-SafeArray->List (vlax-get-property  shed2 'boundaryline)) drains))
    )
  )
       )

 

You might be out of luck:

Command: SA

; error: multi dimension safearray not supported

; reset after error

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...