Jump to content

Filter polyline selection by Z value


chulse
 Share

Recommended Posts

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

Link to comment
Share on other sites

  • Replies 29
  • Created
  • Last Reply

Top Posters In This Topic

  • chulse

    14

  • pBe

    9

  • David Bethel

    5

  • Lee Mac

    2

Top Posters In This Topic

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 **"

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
 

Link to comment
Share on other sites

(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

Link to comment
Share on other sites

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

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

 Share


×
×
  • Create New...