create block from calculation block tags

create block from calculation block tags

Anonymous
Not applicable
1,082 Views
7 Replies
Message 1 of 8

create block from calculation block tags

Anonymous
Not applicable

Hello, first еxcuse me for my english i cant speak very good.

I need a lisp for creating block from calculating other block tags.

I will update file and will explain what i want, if someone can help me i will be very grateful. 🙂 🙂 

If i have block with some tags for terrain and project terrain and i want (block 1 in the file) to create block 2 (when calculation is project terrain - terrain) and from block 2 to create block 3 .

But block 3 is more complicated because in block have (area, average from block 2 and volume from area and the block 2).

I show everything in the file what i need.

Thank you for your attention, i will appreciate​ if someone can help me 🙂 🙂

Happy holidays 🙂

0 Likes
Accepted solutions (2)
1,083 Views
7 Replies
Replies (7)
Message 2 of 8

ВeekeeCZ
Consultant
Consultant
Accepted solution

One more present for ya this year!!

 

(defun c:InsertVolumeBlock ( / *error* und atd atr :GetAttValByTag enl pnt ss i en val lst are avr vol ixd num )
  
  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (if und (command-s "_UNDO" "_Back"))
    (if atd (setvar 'ATTDIA atd))
    (if atr (setvar 'ATTREQ atr))
    (princ))
  
  (defun :GetAttValByTag (blk tag / val)
    (while (= "ATTRIB" (cdr (assoc 0 (setq ed (entget (setq blk (entnext blk)))))))
      (if (= (strcase (cdr (assoc 2 ed))) tag)
	(setq val (read (cdr (assoc 1 (entget blk)))))))
    val)
  
  ;; Set Attribute Value  -  Lee Mac
  ;; Sets the value of the first attribute with the given tag found within the block, if present.
  ;; blk - [ent] Block (Insert) Entity Name
  ;; tag - [str] Attribute TagString
  ;; val - [str] Attribute Value
  ;; Returns: [str] Attribute value if successful, else nil.
  
  (defun LM:setattributevalue ( blk tag val / enx )
    (if (and (setq blk (entnext blk)) (= "ATTRIB" (cdr (assoc 0 (setq enx (entget blk))))))
      (if (= (strcase tag) (strcase (cdr (assoc 2 enx))))
	(if (entmod (subst (cons 1 val) (assoc 1 (reverse enx)) enx))
	  (progn
	    (entupd blk)
	    val))
	(LM:setattributevalue blk tag val))))
  
  
  ; ------------------------------------------------------------------------------------------------------------
  
  (if (and (or (tblsearch "BLOCK" "all")
	       (prompt "\nError: No 'all' block for volume report found in the drawing."))
	   (setq enl (entlast))
	   (setq pnt (getpoint "\nPick Inner point to place the block: "))
	   (vl-cmdf "_.UNDO" "_Mark")
	   (setq und T)
	   (vl-cmdf "_.BOUNDARY" "_Advanced" "_Island" "_No" "" "" "_none" pnt "")
	   (not (equal enl (setq enl (entlast))))
	   (setq ss (ssget "_F"
			   (mapcar '(lambda (y) (trans (cdr y) 0 1))
				   (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget enl)))
			   '((0 . "INSERT") (2 . "project-t*rrain*")))))
    (progn
      (command "_.AREA")
      (repeat (setq i (sslength ss))
	(setq en (ssname ss (setq i (1- i))))
	(if (setq val (:GetAttValByTag en "PROJECT-TRRAIN"))
	  (setq lst (cons val lst)))
	(command (cdr (assoc 10 (entget en)))))
      (command "")
      
      (setq are (getvar 'AREA)
	    avr (abs (/ (apply '+ lst) (float (length lst))))
	    vol (* are avr 0.01)
	    
	    num (getstring "\nBlock number: ")
	    idx (getstring "\nBlock index: ")
	    
	    atd (getvar 'ATTDIA)
	    atr (getvar 'ATTREQ))
      
      (command "_UNDO" "_Back")
      (setq und nil)
      
      (setvar 'ATTDIA 0)
      (setvar 'ATTREQ 1)
      
      (command "_INSERT" "all" "_Scale" 1 "_Rotate" 0 "_none" pnt
	       idx
	       (rtos vol 2 2)
	       (rtos are 2 2)
	       (rtos avr 2 2)
	       num)))
  (*error* "end")
  )

Note: You should consider better names for your blocks. The name 'all' is not very informative. If you do so, search the code and change it there. 

Message 3 of 8

Anonymous
Not applicable

Thank you man i try it, work perfect. 

It was very good gift 🙂 

0 Likes
Message 4 of 8

Anonymous
Not applicable

Hello again

I'm so sorry to bothering you in this time of the year.

I fount a little problem.

I will upload a new test file when i wrote some staff.

If you can change a little the code( to select the block not to click on the middle)

For area we can use selcting polyline or with coordinate with this formula (sum(Xi*(Yi+1 -Yi-1 )))/2.

Thanks a lot, i appreciate what you done and i will understande if you decide not to change the code.

Happy holidays 🙂 🙂 

0 Likes
Message 5 of 8

ВeekeeCZ
Consultant
Consultant

Ok, I got your point. I added the possibility to revise the active selection. You'll still need to pick a point in the middle, but then the routine stops with highlighted blocks and you can add/remove some from the selection. Then the routine continues.

 

The second issue I can see is the wrong attributes assignment. I see that you modified and renamed the OBEM block. Good. But you need to maintain the order of attributes - or change the order in the code. See the command-line listing vs. code:

Command: _INSERT Enter block name or [?] <OBEM>: OBEM Specify insertion point or [Basepoint/Scale/Rotate]: _Scale Specify scale factor for XYZ axes <1>: 0.200000000000000 Specify insertion point or [Basepoint/Scale/Rotate]: _Rotate
Specify rotation angle <0.0000g>: 0 Specify insertion point or [Basepoint/Scale/Rotate]: _none
Enter attribute values
Number: 1 Average: 67.5 Area: 150 Volume: 45 N: 1
(command "_.INSERT" "OBEM" "_Scale" 0.2 "_Rotate" 0 "_none" pnt
	       idx
	       (rtos vol 2 2)
	       (rtos are 2 2)
	       (rtos avr 2 2)
	       num)

You can see that the order is upside-down! Fix that yourself either way.

 

(defun c:InsertVolumeBlock ( / *error* und atd atr :GetAttValByTag enl pnt ss i en val lst are avr vol ixd num )
  
  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (if und (command-s "_UNDO" "_Back"))
    (if atd (setvar 'ATTDIA atd))
    (if atr (setvar 'ATTREQ atr))
    (princ))
  
  (defun :GetAttValByTag (blk tag / val)
    (while (= "ATTRIB" (cdr (assoc 0 (setq ed (entget (setq blk (entnext blk)))))))
      (if (= (strcase (cdr (assoc 2 ed))) tag)
	(setq val (read (cdr (assoc 1 (entget blk)))))))
    val)
  
  ;; Set Attribute Value  -  Lee Mac
  ;; Sets the value of the first attribute with the given tag found within the block, if present.
  ;; blk - [ent] Block (Insert) Entity Name
  ;; tag - [str] Attribute TagString
  ;; val - [str] Attribute Value
  ;; Returns: [str] Attribute value if successful, else nil.
  
  (defun LM:setattributevalue ( blk tag val / enx )
    (if (and (setq blk (entnext blk)) (= "ATTRIB" (cdr (assoc 0 (setq enx (entget blk))))))
      (if (= (strcase tag) (strcase (cdr (assoc 2 enx))))
	(if (entmod (subst (cons 1 val) (assoc 1 (reverse enx)) enx))
	  (progn
	    (entupd blk)
	    val))
	(LM:setattributevalue blk tag val))))
  
  
  ; ------------------------------------------------------------------------------------------------------------
  
  (if (and (or (tblsearch "BLOCK" "OBEM")
	       (prompt "\nError: No 'OBEM' block for volume report found in the drawing."))
	   (setq enl (entlast))
	   (setq pnt (getpoint "\nPick Inner point to place the block: "))
	   (vl-cmdf "_.UNDO" "_Mark")
	   (setq und T)
	   (vl-cmdf "_.BOUNDARY" "_Advanced" "_Island" "_No" "" "" "_none" pnt "")
	   (not (equal enl (setq enl (entlast))))
	   (setq ss (ssget "_F"
			   (mapcar '(lambda (y) (trans (cdr y) 0 1))
				   (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget enl)))
			   '((0 . "INSERT") (2 . "project-t*rrain*"))))
           
           (not (command-s "_.SELECT" ss))
           (setq ss (ssget "_P" '((0 . "INSERT") (2 . "project-t*rrain*"))))
           )
    (progn
      (command "_.AREA")
      (repeat (setq i (sslength ss))
	(setq en (ssname ss (setq i (1- i))))
	(if (setq val (:GetAttValByTag en "PROJECT-TRRAIN"))
	  (setq lst (cons val lst)))
	(command (cdr (assoc 10 (entget en)))))
      (command "")
      
      (setq are (getvar 'AREA)
	    avr (abs (/ (apply '+ lst) (float (length lst))))
	    vol (* are avr 0.01)
	    
	    num (getstring "\nBlock number: ")
	    idx (getstring "\nBlock index: ")
	    
	    atd (getvar 'ATTDIA)
	    atr (getvar 'ATTREQ))
      
      (command "_UNDO" "_Back")
      (setq und nil)
      
      (setvar 'ATTDIA 0)
      (setvar 'ATTREQ 1)
      
      (command "_.INSERT" "OBEM" "_Scale" 0.2 "_Rotate" 0 "_none" pnt
	       idx
	       (rtos vol 2 2)
	       (rtos are 2 2)
	       (rtos avr 2 2)
	       num)))
  (*error* "end")
  )
0 Likes
Message 6 of 8

Anonymous
Not applicable

Hello 

Its good with the select but when i select its stop select.png

Do this and nothing else.

I change the code for my block(OBEM).

Thank you 🙂

0 Likes
Message 7 of 8

ВeekeeCZ
Consultant
Consultant
Accepted solution

Not sure what you're doing wrong. It worked for me well.

Anyway, I changed the code little bit to give little more freedom to a user and also enhanced feedback to give more info what's wrong. Also added a manual-selection mode, because...

 

...one more thing keep in mind. See the AREA command how it works. You need to pick points one by one on a perimeter, never make a zig-zag selection. While you're selecting your PROJEKT-TRRAIN blocks you NEED to similarly go on the perimeter to maintain the order of blocks, because later the routine uses the AREA command. 

 

For the same reason, when you revise your selection and need to ADD some block, better unselect all and start over in order on the perimeter. Hope it's not too complicated. Good luck.

 

 

 

(defun c:InsertVolumeBlock ( / *error* und atd atr :GetAttValByTag enl pnt ss i en val lst are avr vol ixd num man)
  
  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (if und (command-s "_UNDO" "_Back"))
    (if atd (setvar 'ATTDIA atd))
    (if atr (setvar 'ATTREQ atr))
    (princ))
  
  (defun :GetAttValByTag (blk tag / val)
    (while (= "ATTRIB" (cdr (assoc 0 (setq ed (entget (setq blk (entnext blk)))))))
      (if (= (strcase (cdr (assoc 2 ed))) tag)
        (setq val (read (cdr (assoc 1 (entget blk)))))))
    val)
  
  ;; Set Attribute Value  -  Lee Mac
  ;; Sets the value of the first attribute with the given tag found within the block, if present.
  ;; blk - [ent] Block (Insert) Entity Name
  ;; tag - [str] Attribute TagString
  ;; val - [str] Attribute Value
  ;; Returns: [str] Attribute value if successful, else nil.
  
  (defun LM:setattributevalue ( blk tag val / enx )
    (if (and (setq blk (entnext blk)) (= "ATTRIB" (cdr (assoc 0 (setq enx (entget blk))))))
      (if (= (strcase tag) (strcase (cdr (assoc 2 enx))))
        (if (entmod (subst (cons 1 val) (assoc 1 (reverse enx)) enx))
          (progn
            (entupd blk)
            val))
        (LM:setattributevalue blk tag val))))
  
  
  ; ------------------------------------------------------------------------------------------------------------
  
  (if (and (or (tblsearch "BLOCK" "OBEM")
               (prompt "\nError: No 'OBEM' block for volume report found in the drawing."))
           (setq enl (entlast))
           (or (setq pnt (getpoint "\nPick Inner point to place the block <all manual>: "))
               (setq man T))
           (or (and man
                    (not (command-s "_.SELECT")))
               (and (vl-cmdf "_.UNDO" "_Mark")
                    (setq und T)
                    (vl-cmdf "_.BOUNDARY" "_Advanced" "_Island" "_No" "" "" "_none" pnt "")
                    (not (equal enl (setq enl (entlast))))
                    (not (if (setq ss (ssget "_F"
                                             (mapcar '(lambda (y) (trans (cdr y) 0 1))
                                                     (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget enl)))
                                             '((0 . "INSERT") (2 . "project-t*rrain*"))))
                           (command-s "_.SELECT" ss)
                           (command-s "_.SELECT")))))
           (or (setq ss (ssget "_P" '((0 . "INSERT"))))
               (prompt "\nNo blocks selected."))
           (or (> (sslength ss) 2)
               (prompt "\nAt least 3 blocks required."))
           (progn
             (command "_.AREA")
             (repeat (setq i (sslength ss))
               (setq en (ssname ss (setq i (1- i))))
               (if (setq val (:GetAttValByTag en "PROJECT-TRRAIN"))
                 (setq lst (cons val lst)))
               (command (cdr (assoc 10 (entget en)))))
             (command "")
             T)
           (or lst
               (prompt "\nNo blocks with 'PROJECT-TRRAIN' attribute found."))
           )
    (progn
      (setq are (getvar 'AREA)
            avr (abs (/ (apply '+ lst) (float (length lst))))
            vol (* are avr 0.01)
            
            num (getstring "\nBlock number: ")
            idx (getstring "\nBlock index: ")
            
            atd (getvar 'ATTDIA)
            atr (getvar 'ATTREQ))
      
      (and und
           (command "_UNDO" "_Back"))
      (setq und nil)
      
      (setvar 'ATTDIA 0)
      (setvar 'ATTREQ 1)

      (or pnt
          (setq pnt (getpoint "\nPick point to place the block: ")))
      
      (command "_INSERT" "OBEM" "_Scale" 0.2 "_Rotate" 0 "_none" pnt
               num
               (rtos avr 2 2)
               (rtos are 2 2)
               (rtos vol 2 2)
               idx)))
  (*error* "end")
  )
Message 8 of 8

Anonymous
Not applicable

Hello 

It work perfect i so grateful for your help.

I try it and i am soo happy because this save me many hours works 🙂

Happy holidays and Happy new year 🙂 🙂 

0 Likes