Jump to content

Filter polyline selection by Z value


chulse

Recommended Posts

Oh man.. :)

 (strcat "Lay" (itoa (fix elv)))

(strcat "E-TOPO-" (itoa (fix elv)))

 

Kudos to David

 

 

I had set it up that way so it would be easy to change in the future if the project stadards required a different layer naming convention.

 

Besides, wouldn't that make the layer unique or each separate elevation vs. putting all the index contours (any multiples of 10) in the same layer?

Link to comment
Share on other sites

  • Replies 30
  • Created
  • Last Reply

Top Posters In This Topic

  • chulse

    14

  • pBe

    9

  • David Bethel

    5

  • Lee Mac

    2

Top Posters In This Topic

How do we test for the z value being a multiple of 10 though? I don't understand how that is happening...

 

Consider the method utilised in David's code:

 

(defun c:topten (/ ss en)
 (setq s1 (ssadd))
 (and (setq ss (ssget '((0 . "LWPOLYLINE"))))
      (while (setq en (ssname ss 0))
             (if (zerop (rem (cdr (assoc 38 (entget en))) 10))
                 (ssadd en s1))
             (ssdel en ss)))

s1)

Specifically, this line:

 

[b][color=GREEN]([/color][/b]zerop [b][color=BLUE]([/color][/b]rem [b][color=RED]([/color][/b]cdr [b][color=PURPLE]([/color][/b]assoc 38 [b][color=TEAL]([/color][/b]entget en[b][color=TEAL])[/color][/b][b][color=PURPLE])[/color][/b][b][color=RED])[/color][/b] 10[b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b]

Breaking this down into its individual expressions, we first have:

 

(cdr (assoc 38 (entget en)))

As you may have gathered, the DXF 38 group code is the elevation of the LWPolyline, hence the above expression returns this elevation value.

 

Substituting this knowledge into the original expression, we have:

 

(zerop (rem [color=red]<Elevation>[/color] 10))

Now study the rem function in more detail.

 

From the Visual LISP IDE Help Docs:

 

rem

 

Divides the first number by the second, and returns the remainder.

 

([color=blue]rem [/color][color=darkred][number number...][/color])

Arguments

 

number

Any number.

 

Return Values

 

A number. If any number argument is a real, rem returns a real; otherwise, rem returns an integer. If no arguments are supplied, rem returns 0. If a single number argument is supplied, rem returns number.

 

Now that we know what the rem function is doing, let us take a look at the zerop function, which is operating on the result of the rem function:

 

zerop

 

Verifies that a number evaluates to zero.

 

([color=blue]zerop [/color][color=darkred]number[/color])

Arguments

 

number

A number.

 

Return Values

 

T if number evaluates to zero; otherwise nil.

 

Hence, in conclusion, the rem function returns the remainder from dividing the elevation by 10, then the zerop function returns T if such remainder is zero, i.e. if the elevation is a multiple of 10.

 

If ever you want to understand what a line of code is doing, break the line down, expression by expression and study each function that is being evaluated, and what that function is returning as a result.

 

[ EDIT: Looks like I am too slow at typing! ]

Link to comment
Share on other sites

Thanks guys for all the help.

This is the fully functional version.

 

The only thing I haven't figured out yet is why the FOREACH wasn't working to set the layer... but David's command version works perfectly. Thanks again.

 

(defun C:SCL (/ *error* msg ELEV SS LAY2 LAY10 DOC UFLAG ALL obj temp s1 en)
 
 ;layer name used for 10' contours
 (setq lay10 "E-TOPO-10")
 
 ;layer name used for 2' contours
 (setq lay2 "E-TOPO-2")
 
   (vl-load-com)
 (setq DOC (vla-get-ActiveDocument (vlax-get-acad-object)))

 ;; --{  Error Handler Function by Lee Mac }--
 (defun *error* (msg)     
   (and uflag (vla-EndUndoMark doc))
   
   (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")        
       (princ (strcat "\n** Error: " msg " **")))    
   (princ))  

 ;; --{  Main Function  }-- 
 (setq uflag (not (vla-StartUndoMark doc)))
 
 ;;; CHECK FOR LAYER AND ADD IF NOT EXIST
           (or (tblsearch "LAYER" LAY10)
           (vla-add (vla-get-layers doc) LAY10))
           
           (or (tblsearch "LAYER" LAY2)
           (vla-add (vla-get-layers doc) LAY2))
           
   ;put all obj on 2' contour layer        
  (setq all (ssget "_X" '((0 . "LWPOLYLINE") )))         
           
;;;            (foreach obj all
;;;            (vla-put-layer (vlax-ename->vla-object obj) LAY2)
;;;            );_end foreach
   (command "_.CHPROP" all "" "_LA" lay2 "")
   
;(find all contours from 10 to 10000 by 10)
   
 ; (setq elev 10 ss (ssadd))
 ; (while 
 ; (<= elev 10000);max elevation searched for is 10,000 feet - change if need be
   ; (if (setq temp (ssget "_X" (List '(0 . "LWPOLYLINE") (cons 38 elev))))
; (repeat (setq i (sslength temp))
     ; (ssadd  (ssname temp (setq i (1- i))) ss)))
        ; (setq elev (+ elev 10))
 ; );_end while
 
   (setq s1 (ssadd))
 (and (setq ss (ssget "_X" '((0 . "LWPOLYLINE"))))
      (while (setq en (ssname ss 0))
             (if (zerop (rem (cdr (assoc 38 (entget en))) 10))
                 (ssadd en s1))
             (ssdel en ss)))
       ;;;s1)
 
 ;put 10' contours on correct new layer
;;;            (foreach obj S1
;;;            (vla-put-layer obj Lay10)
;;;            );_end foreach
    (command "_.CHPROP" s1 "" "_LA" lay10 "")
   
   ;clear ss
   (setq s1 nil)
    (setq all nil)   
 (setq uFlag (vla-EndUndoMark doc))
 (princ)
 );_end defun

Link to comment
Share on other sites

,,,,, putting all the index contours (any multiples of 10) in the same layer?

 

Thats exactly what the code is doing , [see code at post # 16] with that approach you eliminate the need for . (ssadd)

For every DXF 38 value found to be true undet the condition [as explained by DB and LM] it wiil assign a layer name equiivalent to your naming convention.

Say first item on selection sets elevation is at 10.0 , which means the condtion is true , it then converts the dxf value of 10.0 to "10" and pass the argument for strcat to make "E-TOPO-10". so same goes of every TRUE statement. DXF 38 value 50.0 to "E-TOPO-50".

The layer name will depend on the elevation value. which means a dxf value of 10 will still be assinged to "E-TOPO-10".

 

Got it?

Link to comment
Share on other sites

Building on Davids code

....
             (if (zerop (rem [color=blue][b](setq elv[/b][/color] (cdr (assoc 38 [color=blue][b](setq e[/b][/color] (entget en))))) 10))
                [color=blue][b](entmod (subst (cons 8 (strcat [color=darkgreen]"E-TOPO-"[/color] (itoa (fix elv))))[/b][/color]
[b][color=blue]                           (assoc 8 e) e))[/color][/b]
)

 

I like that. Nice and neat yet still human readable. -David

Link to comment
Share on other sites

ohhhh geez.. I see what you mean cary , exlcusively "E-TOPO-10" which means intervals of 10. My bad then.

 

so it should be

[b][color=#0000ff](entmod (subst (cons 8 [/color][color=darkgreen]"E-TOPO-10")[/color][/b]
[b][color=blue]                           (assoc 8 e) e))[/color][/b]
                 )

 

Im not for really cut CIVIL works :lol:

Apologies guys

Link to comment
Share on other sites

I like that. Nice and neat yet still human readable. -David

 

:lol: Never got around writing "color syntax" myself and stick with them available toolbars.

 

Kudos to you David for that condtional statement construct :thumbsup:

Link to comment
Share on other sites

  • 12 years later...
On 29/04/2012 at 00:57, chulse said:

Thanks guys for all the help.

This is the fully functional version.

 

The only thing I haven't figured out yet is why the FOREACH wasn't working to set the layer... but David's command version works perfectly. Thanks again.

 

 

(defun C:SCL (/ *error* msg ELEV SS LAY2 LAY10 DOC UFLAG ALL obj temp s1 en)
 
 ;layer name used for 10' contours
 (setq lay10 "E-TOPO-10")
 
 ;layer name used for 2' contours
 (setq lay2 "E-TOPO-2")
 
   (vl-load-com)
 (setq DOC (vla-get-ActiveDocument (vlax-get-acad-object)))

 ;; --{  Error Handler Function by Lee Mac }--
 (defun *error* (msg)     
   (and uflag (vla-EndUndoMark doc))
   
   (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")        
       (princ (strcat "\n** Error: " msg " **")))    
   (princ))  

 ;; --{  Main Function  }-- 
 (setq uflag (not (vla-StartUndoMark doc)))
 
 ;;; CHECK FOR LAYER AND ADD IF NOT EXIST
           (or (tblsearch "LAYER" LAY10)
           (vla-add (vla-get-layers doc) LAY10))
           
           (or (tblsearch "LAYER" LAY2)
           (vla-add (vla-get-layers doc) LAY2))
           
   ;put all obj on 2' contour layer        
  (setq all (ssget "_X" '((0 . "LWPOLYLINE") )))         
           
;;;            (foreach obj all
;;;            (vla-put-layer (vlax-ename->vla-object obj) LAY2)
;;;            );_end foreach
   (command "_.CHPROP" all "" "_LA" lay2 "")
   
;(find all contours from 10 to 10000 by 10)
   
 ; (setq elev 10 ss (ssadd))
 ; (while 
 ; (<= elev 10000);max elevation searched for is 10,000 feet - change if need be
   ; (if (setq temp (ssget "_X" (List '(0 . "LWPOLYLINE") (cons 38 elev))))
; (repeat (setq i (sslength temp))
     ; (ssadd  (ssname temp (setq i (1- i))) ss)))
        ; (setq elev (+ elev 10))
 ; );_end while
 
   (setq s1 (ssadd))
 (and (setq ss (ssget "_X" '((0 . "LWPOLYLINE"))))
      (while (setq en (ssname ss 0))
             (if (zerop (rem (cdr (assoc 38 (entget en))) 10))
                 (ssadd en s1))
             (ssdel en ss)))
       ;;;s1)
 
 ;put 10' contours on correct new layer
;;;            (foreach obj S1
;;;            (vla-put-layer obj Lay10)
;;;            );_end foreach
    (command "_.CHPROP" s1 "" "_LA" lay10 "")
   
   ;clear ss
   (setq s1 nil)
    (setq all nil)   
 (setq uFlag (vla-EndUndoMark doc))
 (princ)
 );_end defun
 

 

 

 

Thankyou for this, is there any chance of modifying it for a 2DPolyline and only filtering on a specific wildcard layer.

 

IE. Command runs only on the wildcard *Contour* layers

 

I tried changing LWPOLYLINE to *POLYLINE with no luck, only changes everything to a minor contour.

Edited by KraZeyMike
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...