Gather list data from all blocks in a layer

Gather list data from all blocks in a layer

etilley327KA
Advocate Advocate
2,139 Views
34 Replies
Message 1 of 35

Gather list data from all blocks in a layer

etilley327KA
Advocate
Advocate

How might I go about getting the nested information from all the blocks in a layer.

0 Likes
Accepted solutions (2)
2,140 Views
34 Replies
Replies (34)
Message 21 of 35

etilley327KA
Advocate
Advocate

Haha. Just noticed I replied to the wrong person. Thanks for the info Sea-Haven

0 Likes
Message 22 of 35

etilley327KA
Advocate
Advocate

I appreciate the coding; I'm still staring at it and looking up terminology.

0 Likes
Message 23 of 35

etilley327KA
Advocate
Advocate

etilley327KA_0-1667504314442.gif

Ok, after staring at your code for a considerably long time I've come to a few conclusions. First, man there so much to learn. Second, I was able to slightly understand what you did except the vl-sort function and I'm unfamiliar with entmake DXF table entries. I've spent a considerable amount of time trying to modify your code, but with errors at every turn. I tried to limit the "a" list to just the lowest and the highest numbers. Also, I attempted to modify the entmake, but I must have the formatting wrong. Could you explain how that works? Can you still add all the other DXF modifiers? Thanks again for all your help.

0 Likes
Message 24 of 35

Sea-Haven
Mentor
Mentor

Re dxf data you can google just that say "dxf line autocad" it will point to help about dxf codes.

 

This is another simple way to look at an object (entget (car (entsel "\nPick object"))) it will show dxf codes but you have to sometimes have a understanding what your looking at.

 

0 Likes
Message 25 of 35

ВeekeeCZ
Consultant
Consultant

Ok, I'll stop posting spoilers because staring at anything for hours, no matter how pleasant that could possibly be,  never helped anybody. 

 

Maybe it's my English, but the 'a' variable from my code is not a list. It stores a value of "PT#" att, and they are always strings. So if that represents a number, needs to be converted.

 

If you need to filter your list, we would typically use vl-remove-if/not HERE 

But is also possible to use a basic foreach and rebuild a list. (foreach e l (if (< (car e) mymostfavouritenumber)) (setq n (cons e n)))

 

(entmake)ing isn't necessary, you can use simple (command)... and (foreach) to cover all points non knowing how many.

(command "_.pline") 
(foreach e l (command "_non" (cdr e)))
(command "")))

 

And yes, vl-sort is... especially tricky. Only magicians of the fourth level and above manage to handle that.

 

 

 

0 Likes
Message 26 of 35

etilley327KA
Advocate
Advocate

Well crap, I've learned a lot, but not enough to put any of this together. Is this the simplest way to do this. I guess when I set out to do this I assumed it would be slightly easier. I still don't think I'm quite there. Could you help me with a simplified code or maybe there isn't in which case ill continue to read and watch videos and see if I can understand what you've already given me, of which I am very appreciative. I still have another similar lisp Id like to work on and if I could make sense of this, perhaps I could write that one by myself. 

 

(defun c:FDERT ( / fs i e fsn fsd)
Pull objects with name "insert", block name "srvpno5" and layer "shot"
(if (setq fs (ssget "_X" '((0 . "INSERT")
(2 . "SRVPNO5")
(8 . "SHOT")
)))

This cycles through and extracts the data from the objects collected earlier
(repeat (setq i (sslength s))
(setq e (ssname fs (setq i (1- i))))

This is where things get fuzzy. Maybe something like (apply 'max and 'min) to reduce the data to 2 numbers

Im not exactly sure of all the syntax on what you wrote below, but I think it creates a list of the X and Y of "e"

(setq l (cons (list (atoi a) (getpropertyvalue e "Position/X") (getpropertyvalue e "Position/Y")) l)))))

Little confused on how to apply this, but with the X and Y of two points I could entmake a line and place " in DXF 10 and 11 while able to cons it with given layer, color etc.

Appreciate any help. Thanks again.

0 Likes
Message 27 of 35

ВeekeeCZ
Consultant
Consultant

Here's the simplest way... 

 

(vl-load-com)

(defun c:ConnectByPointNumbers ( / s i e l)
  
  (if (setq s (ssget "_A" '((0 . "INSERT")
			    (2 . "SRVPNO5")
			    ;(8 . "SHOT")
			    )))
    (repeat (setq i (sslength s))
      (setq e (ssname s (setq i (1- i)))) ; e is ename, looks like this: 
      (if (not (vl-catch-all-error-p (setq a (vl-catch-all-apply 'getpropertyvalue (list e "PT#")))))
	(setq l (cons (list (atoi a)  ; pointnumber
			    (getpropertyvalue e "Position/X")
			    (getpropertyvalue e "Position/Y"))
		      l)))))
  ; l is a list of lists descibing all selected points '( (pointnumber1 X-coord1 Y-coord1) (pointnumber2 X-coord2 Y-coord2) (pointnumber3 X-coord3 Y-coord3) ....)
  
  (and l
       
       (setq l (vl-sort l '(lambda (e1 e2) (< (car e1) (car e2))))) ;; sorts a list by it's first member (which is pointnumber), from the lower to the highest
       
       (setq pmin (cdar l))
       (setq pmax (cdr (last l)))
       
       (entmake (append (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(70 . 0)  (cons 90 (length l)))
			(mapcar '(lambda (p) (cons 10 (cdr p))) l))))
  (princ)
  )

 

Message 28 of 35

etilley327KA
Advocate
Advocate

Man, do you even sleep. Thanks, if this is the simplest way then looks like I got some edumacating to do. Thanks again for everything.

0 Likes
Message 29 of 35

ВeekeeCZ
Consultant
Consultant

Actually, what exactly do you want? A Line connecting two points of global min and max PT#?

0 Likes
Message 30 of 35

etilley327KA
Advocate
Advocate

Yes sir, with this lisp I'm going for connecting the highest point with the lowest point, with a line on a specific layer and color. I am still gonna figure out how you did exactly what you did. So I can replicate it in a different fashion later. You've been such a big help.

0 Likes
Message 31 of 35

ВeekeeCZ
Consultant
Consultant
Accepted solution

IMHO The simplest.

 

(vl-load-com)

(defun c:ConnectMinMax ( / s i e a amin amax pmin pmax)
  
  (if (setq s (ssget "_A" '((0 . "INSERT")
			    (2 . "SRVPNO5")
			    ;(8 . "SHOT")
			    )))
    (repeat (setq i (sslength s))
      (setq e (ssname s (setq i (1- i))))
      (setq a (atoi (getpropertyvalue e "PT#")))
      
      (if (/= a 0)  ; 0 if blank "PT#"
	(progn
	  (if (or (not amin)
		  (< a amin)
		  )
	    (setq amin a
		  pmin (getpropertyvalue e "Position")))
	  
	  (if (or (not amax)
		  (> a amax)
		  )
	    (setq amax a
		  pmax (getpropertyvalue e "Position")))))))
  
  (if (and pmax pmin)
    (command "_.line" "_non" pmin "_non" pmax ""
	     "_.chprop" "_last" "" "_layer" "0" "_color" 1 ""))
  
  (princ)
  )

 

Message 32 of 35

etilley327KA
Advocate
Advocate

Very very appreciative, I spent time looking over and researching the code you sent me this weekend and while I'm still not clear on everything I've learned a lot and will continue to further my understanding of the code and how it worked. Thanks once again.

0 Likes
Message 33 of 35

Sea-Haven
Mentor
Mentor

If I read your 1st post correct I should have looked at this way more closely, having done civil works for way to many years, you have block points with a description, so its easy to do a string all points based on description, this is built in to CIV3D.

 

If we look at a point file it would look like PT,X,Y,Z,Desc. You basically take all points and sort on description joining common descriptions. You set up a look up library so correct layers, blocks etc are associated with points.

 

I would look into a 3rd party program like "Stringer" https://stringersurvey.com.au/

 

It does way more than just string points together, surfaces etc. 

 

Ok if you want to have a go its simple, read all blocks and make a list of ((desc entityname)....) sort the list based on description the join the points together reading next point, next point, change of desc new layer etc.

 

Ok I have been doing this for like 40 years, so you can add to your description code stuff like 41*C meaning close. In your dwg you have green and purple lines for "41" so you could do this using what is known as a string so 0141 would be green 0241 would be green but it does not join to 0141 lines so can change its color but maintain layer. Yes stuff like arcs can be done in the description as well.

 

Just a quick comment if you get the stringing wrong you get a bowl of spaghetti. 

Message 34 of 35

etilley327KA
Advocate
Advocate

Wow! That sounds like something I was looking for, thanks once again. So many possibilities, really cool.

0 Likes
Message 35 of 35

Sea-Haven
Mentor
Mentor

You have a library of matching descriptions

 

SeaHaven_0-1667876286826.png