Jump to content
chulse

Filter polyline selection by Z value

Recommended Posts

chulse

Could someone help point me in the right direction here? I want to filter a selection of polylines (contour lines) by their Z value (ie filter to get only 10' or 5' or 2' contours).

I assume I need to test the Z value to see if it is a muliple of 10, 5 or 2, etc...

 

Any hints on hhow to get this sarted?

 

Thanks

Share this post


Link to post
Share on other sites
David Bethel

Are these LWPOLYLINES or Heavy POLYLINEs ? -David

Share this post


Link to post
Share on other sites
chulse

I'm not sure. I'll have to find out - i'm working on this for my sister.

Share this post


Link to post
Share on other sites
Lee Mac

To check the Polyline type, load this and pick a Polyline:

 

(defun c:checkpoly ( / e )
   (if (setq e (car (entsel)))
       (print (cdr (assoc 0 (entget e))))
   )
   (princ)
)

 

If the above returns "LWPOLYLINE", you can filter the selection by the LWPolyline Elevation value, DXF 38:

 

(ssget "_X" '((0 . "LWPOLYLINE") (38 . <YourElevationValue>)))

 

If the above returns "POLYLINE", things are a little more complicated, since the Z value will be contained in the coordinate of each vertex. Such vertices are not primary entities and hence cannot be filtered using an ssget filter list.

 

For this case, you would need to collect a set of all such Polylines, then iterate over this set removing those which do not have the correct vertex elevation.

Share this post


Link to post
Share on other sites
chulse

Thanks guys. I'll have to get one of her drawings and play with it.

Share this post


Link to post
Share on other sites
pBe

Sample Code

(defun c:test (/ elev ss)
 (initget 1 "2 5 10 ALL")
 (setq elev (getkword "\nSelect String for filter [2/5/10/ALL]: "))
 (setq ss (ssget "_X" (if (eq elev "ALL")
   '((0 . "LWPOLYLINE")
      (-4 . "<OR")
      (38 . 24.0)
      (38 . 60.0)
      (38 . 120.0)
      (-4 . "OR>")
    )  
  (list '(0 . "LWPOLYLINE")  
      (cons 38  (* 12  (distof elev)))
        )
  )
   )
   )
 (sssetfirst nil ss)
)

Share this post


Link to post
Share on other sites
chulse

Thanks pBe. You must be an architect - it took me a few to realize you were looking at inches. These are topo contour lines (all in feet).

 

I think I managed to work out the general concept, but I am getting an error with the SSGET list. (bad SSGET list)

 

What I need to do (I think) is step through all possible 10' elevations and add each to a SS as we go. In the end, the goal is to find all of them (any elvation that's a multiple of 10) and move it to a specific layer.

 

  (setq elev 10)
 (while 
 (<= elev 10000)
   (setq temp (ssget "_X" '((0 . "LWPOLYLINE") (cons '38 elev))))
   (setq ss (ssadd ss temp))
    (setq temp nil)
 (setq elev (+ elev 10))
 );_end while

 

I'm a bit stumped why I am getting the error. Any help much appericated.

 

Thanks

Share this post


Link to post
Share on other sites
pBe

Try this way

               
[b][color=blue](defun c:demo (/ elev ss i)[/color][/b]
(setq elev 10 [color=blue][b]ss (ssadd)[/b][/color][color=black])[/color]
 (while 
 (<= elev 10000)
  [color=blue][b] (if (setq temp (ssget "_X" (List '(0 . "LWPOLYLINE") (cons 38 elev))))[/b][/color]
[color=blue][b](repeat (setq i (sslength temp))[/b][/color]
[color=blue][b]      (ssadd  (ssname temp (setq i (1- i))) ss)))[/b][/color]
        (setq elev (+ elev 10))
 );_end while
[b][color=blue](sssetfirst nil ss)[/color][/b]
              )

 

I guess you guys use DECIMAL Feet, I seldom deal with units other than architectural , only when i'm "forced" to do grading. :)

Share this post


Link to post
Share on other sites
chulse

thanks

Yes, everything is decimal, so I didn't realize at first what your code was doing :)

Share this post


Link to post
Share on other sites
pBe

you might find this one interesting though

 
(defun c:demo  (/ elev ss)
     (setq elev 10
           ss   (ssadd))
     (while
           (<= elev 10000)
                (if (setq temp (ssget "_X"
                                      (List '(0 . "LWPOLYLINE")
                                            [color=blue][b]'(-4 . "<OR")[/b][/color]
[b][color=blue]                                            (cons 38 elev)[/color][/b]
[b][color=blue]                                            (cons 38 (- elev))[/color][/b]
[b][color=blue]                                            '(-4 . "OR>")[/color][/b]
                                            )))
                      (repeat (setq i (sslength temp))
                            (ssadd (ssname temp (setq i (1- i))) ss)))
                (setq elev (+ elev 10))
                ) ;_end while
     (sssetfirst nil ss)
     )

 

It includes negative intervall of 10 as well ;)

Share this post


Link to post
Share on other sites
chulse

cool, although i don't think i'll ever need to deal with elevations below sea level (at least not on the east coast of the US)

 

My next issue is this - i assumed i could use FOREACH to set the layer of the entities in the SS, but it seems not.

is the concept bad or just my syntax?

 

;put 10' contours on correct new layer
           (foreach obj SS
           (vla-put-layer obj Lay10)
           );_end foreach

 

it returns this "** Error: bad argument type: consp **"

Share this post


Link to post
Share on other sites
David Bethel

My guess is that it would be simple just to step through a PICKSET of LWPOLYLINEs

 

 

[b][color=BLACK]([/color][/b]defun c:topten [b][color=FUCHSIA]([/color][/b]/ ss en[b][color=FUCHSIA])[/color][/b]
 [b][color=FUCHSIA]([/color][/b]setq s1 [b][color=NAVY]([/color][/b]ssadd[b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b]
 [b][color=FUCHSIA]([/color][/b]and [b][color=NAVY]([/color][/b]setq ss [b][color=MAROON]([/color][/b]ssget '[b][color=GREEN]([/color][/b][b][color=BLUE]([/color][/b]0 . [color=#2f4f4f]"LWPOLYLINE"[/color][b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
      [b][color=NAVY]([/color][/b]while [b][color=MAROON]([/color][/b]setq en [b][color=GREEN]([/color][/b]ssname ss 0[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b]
             [b][color=MAROON]([/color][/b]if [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]
                 [b][color=GREEN]([/color][/b]ssadd en s1[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b]
             [b][color=MAROON]([/color][/b]ssdel en ss[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b]

s1[b][color=BLACK])[/color][/b]

 

 

Even if you select _All

 

-David

Share this post


Link to post
Share on other sites
pBe
My guess is that it would be simple just to step through a PICKSET of LWPOLYLINEs

.......(zerop (rem (cdr (assoc 38 (entget en))) 10))....

Even if you select _All

 

-David

 

Brilliant :thumbsup:

 

 

(foreach obj SS,,,,

You cant use foreach on a pickset Cary

 

(vla-put-layer obj Lay10)

Need a vla-object + a valid layer

Share this post


Link to post
Share on other sites
chulse

Ok, so if I understand - we select all LWPOLYLINES, then filter out all the ones that are multiples of ten?

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

 

Then, what's the best way to change the layer of the entities in the selection set?

 

Thanks

Share this post


Link to post
Share on other sites
chulse
Brilliant :thumbsup:

 

 

 

You cant use foreach on a pickset Gary

 

 

Need a vla-object + a valid layer

 

So I need to convert the OBJ to a VLA-Object first then?

Share this post


Link to post
Share on other sites
pBe

Not necesarily...Tell us, after the layer thingy, what else do you need to do?

 

If thats all there is to it. you dont need to create another selection set

 

Building on Davids code

(defun c:topten (/  en e )
 (and (setq ss (ssget '((0 . "LWPOLYLINE"))))
      (while (setq en (ssname ss 0))
             (if (zerop (rem (cdr (assoc 38 [color=blue][b](setq e[/b][/color] (entget en)))) 10))
                [color=blue][b](entmod (subst (cons 8 [color=green]"E-TOPO-10")[/color][/b][/color]
[b][color=blue]                        (assoc 8 e) e))[/color][/b]
                 )
             (ssdel en ss)))
)

 

UPDATED

Edited by pBe
EDIT : CIVIL MODE

Share this post


Link to post
Share on other sites
chulse

that's all - the goal is to find all the index contours (multiples of 10) and set them on a specific layer.

I will probably try to set all the remaining contours on a different layer also.

 

these contours all come from imported GIS data and the sets can be huge, so doing this manually is all but impossible.

 

this is what I have at the moment:

 

(defun C:SCL (/ *error* msg ELEV SS LAY2 LAY10 DOC UFLAG ALL obj temp)

 ;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  }--
 (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 obj LAY2)
           );_end foreach


;(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


 ;put 10' contours on correct new layer
           (foreach obj SS
           (vla-put-layer obj Lay10)
           );_end foreach

   ;clear ss
   (setq ss nil)
    (setq all nil)   
 (setq uFlag (vla-EndUndoMark doc))
 (princ)
 );_end defun
 

Share this post


Link to post
Share on other sites
David Bethel

(if (zerop (rem (cdr (assoc 38 (entget en))) 10))

 

IF the remainder of dividing the LWPOLYLINE elevation (cdr (assoc 38 (entget en))) by 10 is zerop

THEN add the ENAME to the PICKSET

 

 

I'm still a command guy at heart:

 

If the layer exists:

(command "_.CHPROP" s1 "" "_LA" "layer_name" "")

 

-David

Share this post


Link to post
Share on other sites
pBe
that's all - the goal is to find all the index contours (multiples of 10) and set them on a specific layer.

I will probably try to set all the remaining contours on a different layer also.

 

 

 
;layer name used for 10' contours
(setq lay10 "E-TOPO-10")

;layer name used for 2' contours
(setq lay2 "E-TOPO-2")

 

Oh man.. :)

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

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

 

Kudos to David

Share this post


Link to post
Share on other sites
chulse

Thanks for the explanation. That makes perfect sense.

Share this post


Link to post
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
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  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...