Author Topic: Adding block type to a list  (Read 851 times)

0 Members and 1 Guest are viewing this topic.

jerryman

  • Mosquito
  • Posts: 3
Adding block type to a list
« on: June 10, 2024, 07:10:13 PM »
Hello everyone,

First post, thanks for your time in advance.

I have a command that will, like many others I've seen, allow selection of blocks, ask for an additional point and print them. My goal was to utilize the list data to draw polylines, but I want to add additional fields to the list for later use. I've simplified some of this just to show what code I have that functions properly, I'm having issues understanding how to add the other items to the list or sublist. This is totally out of ignorance but I'm trying to learn more, if I wanted to introduce this option what functions would be the best to use?

Concept:
Check blockname list for AA, if AA exist then AA is arc.

Modified example of current output of the code below (it would normally only have one userpt as intended):
Block Coordinates and Names:
((BLOCK1_XXAAXX (921.866 1042.21 246.0)) (UserPt (860.866 992.962 246.0)))
((BLOCK1_XXBBXX (860.866 992.962 246.0)) (UserPt (440.866 992.962 246.0)))

Desired output:
Block Coordinates and Names:
((BLOCK1_XXAAXX (921.866 1042.21 246.0)) (UserPt (860.866 992.962 246.0)) arc)
((BLOCK1_XXBBXX (860.866 992.962 246.0)) (UserPt (440.866 992.962 246.0)) straight)

Code: [Select]
(defun c:mycmd ( / ss ent inscoords blockname coordlist userpt)
  (setq ss (ssget '((0 . "INSERT"))))
  (setq coordlist (list))
  (if ss 
    (progn
      (setq ent (ssname ss 0))
      (while ent
        (setq inscoords (cdr (assoc 10 (entget ent))))
        (setq blockname (cdr (assoc 2 (entget ent))))
        (setq coordlist (append coordlist (list (list blockname inscoords))))
        (setq ss (ssdel ent ss))
        (setq ent (ssname ss 0))
      )
      (setq userpt (getpoint "\nSelect end point of last block selected: "))
      (setq coordlist (append coordlist (list (list "UserPt" userpt))))
      (princ "\nBlock Coordinates and Names: ")
      (princ coordlist)
    )
    (princ "\nNo blocks selected.")
  )
  (princ) ; Ensure function returns nil
)

Thanks and regards,
jerryman

BIGAL

  • Swamp Rat
  • Posts: 1474
  • 40 + years of using Autocad
Re: Adding block type to a list
« Reply #1 on: June 10, 2024, 08:37:37 PM »
Fairly simple use the COND function to compare block name with type.

Code: [Select]
(cond
((= "BLOCK1_XXAAXX" blockname)(setq typ "Arc"))
((= "BLOCK1_XXBBXX" blockname)(setq typ "Straight"))
((= "BLOCK1_XXCCXX" blockname)(setq typ "ZIGZAG"))
)
A man who never made a mistake never made anything

Tharwat

  • Swamp Rat
  • Posts: 712
  • Hypersensitive
Re: Adding block type to a list
« Reply #2 on: June 11, 2024, 08:09:53 AM »
Hopefully this meets what you are after.
NOTE: You can add more block names & types as declared in the following codes in 'grp' list.
Code - Auto/Visual Lisp: [Select]
  1. (defun c:Test (/ grp pnt int sel ent get fnd lst)
  2.   ;;----------------------------------------------------;;
  3.   ;;    Author : Tharwat Al Choufi                      ;;
  4.   ;; website: https://autolispprograms.wordpress.com    ;;
  5.   ;;----------------------------------------------------;;
  6.   (setq grp '(("XX_AA_XX" "Arc")
  7.               ("XX_BB_XX" "Straight")
  8.              )
  9.   )
  10.   (and
  11.     (setq pnt (getpoint "\nSelect end point of last block selected: "))
  12.     (princ "\nSelect your desired blocks : ")
  13.     (or (setq int -1
  14.               sel (ssget '((0 . "INSERT")))
  15.         )
  16.         (princ "\nNo blocks selected.")
  17.     )
  18.     (or (while (setq int (1+ int)
  19.                      ent (ssname sel int)
  20.                )
  21.           (and (setq fnd (assoc (cdr (assoc 2 (setq get (entget ent)))) grp))
  22.                (setq
  23.                  lst (cons (list pnt (cdr (assoc 10 get)) (cadr fnd)) lst)
  24.                )
  25.           )
  26.         )
  27.         t
  28.     )
  29.     (and lst (princ lst))
  30.   )
  31.   (princ)
  32. )

jerryman

  • Mosquito
  • Posts: 3
Re: Adding block type to a list
« Reply #3 on: June 11, 2024, 01:22:49 PM »
Thanks @BIGAL and @Tharwat

@Tharwat, what section of your code would check the list to see if the block name contains these matches and then adds the block type to the list?

I noticed the block names are very long but have a few obvious and defining factors in their names. Below the block names, "have been changed to protect the innocent" but these are well thought out alternatives. As you can see there is quite a bit of overlap in the block names, I've added the spaces to the block names to make them easier to read.

The arc blocks, while many other block names are arcs, they would all contain these in their name. Maybe treat these as static if block name contained an exact match, then arc? I think I can treat the straight blocks the same, if they contain these exact matches, then straight.
commonalities:
arc:
abc xy de
abc de

I think I can treat the straight blocks the same, if they contain these exact matches, then straight.
straight:
123 abc
123 abc xy
45 abc
45 abc xy
456 abc
456 abc xy
457 abc
457 abc xy


I tried to get this to work previously but was unsuccessful:
Code: [Select]
        (cond
            ((or
                (wcmatch blockname "*abc xy de*")
                (wcmatch blockname "*abc de*")
            )
            (setq blocktype "arc"))
            ((or
                (wcmatch blockname "*123 abc*")
                (wcmatch blockname "*123 abc xy*")
                (wcmatch blockname "*45 abc*")
                (wcmatch blockname "*45 abc xy*")
                (wcmatch blockname "*456 abc*")
                (wcmatch blockname "*456 abc xy*")
                (wcmatch blockname "*457 abc*")
                (wcmatch blockname "*457 abc xy*")
            )
            (setq blocktype "straight"))
        )


ribarm

  • Gator
  • Posts: 3328
  • Marko Ribar, architect
Re: Adding block type to a list
« Reply #4 on: June 11, 2024, 04:19:09 PM »
Since you are repeating block structure with same syntaxes from arc to straight types, these 2 are wrongly written :
(wcmatch blockname "*abc xy de*")
(wcmatch blockname "*abc de*")

You should change them to names without starting *...
(wcmatch blockname "abc xy de*")
(wcmatch blockname "abc de*")
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

jerryman

  • Mosquito
  • Posts: 3
Re: Adding block type to a list
« Reply #5 on: June 18, 2024, 07:15:40 PM »
Thanks everyone for the responses, this has been most helpful! I wanted to share the final working section of this code, was so excited to finally make working command. I've been working on this in sections to try and make it easier to debug. The goal now is to interact with the list that has been labeled as "Arc".

The PLINE is primarily acting as a centerline where I will fillet with a radius measurement and then offset multi on each side then erase the centerline. The main reason behind this is I haven't figured out how to draw the PLINE on the desired offset points relative to its perpendicular location. I can normally manually draw this PLINE fast, but it really should be automated. Once I realized the block insertion points could easily draw a centerline path, I knew I had to try and automate this crap!

Came to the conclusion it was pointless to determine if the block was straight because the arc would be the one I need to interact with in the list.

Code: [Select]
(defun c:mytestcmd ( / ss ent inscoords blockname coordlist userpt blocktype)
    ; Helper function to determine if a block is a "Arc"
    (defun isArcBlock (blockname)
        (cond
            ((vl-string-search "abc xy de" blockname) "Arc")
            ((vl-string-search "abc de cba" blockname) "Arc")
            ((vl-string-search "abc de" blockname) "Arc")
            ((vl-string-search "abc xy de ba" blockname) "Arc")
            (t nil)))

    ; Select blocks of type "INSERT"
    (setq ss (ssget '((0 . "INSERT"))))
    (setq coordlist (list))

    (if ss
        (progn
            ; Gather block names and coordinates
            (setq ent (ssname ss 0))
            (while ent
                (setq inscoords (cdr (assoc 10 (entget ent))))
                (setq blockname (cdr (assoc 2 (entget ent))))
                (setq blocktype (isArcBlock blockname))
                (setq coordlist (append coordlist (list (list blockname inscoords blocktype))))
                (setq ss (ssdel ent ss))
                (setq ent (ssname ss 0))
            )

            ; Get user-selected point
            (setq userpt (getpoint "\nSelect end point of last block selected: "))
            (setq coordlist (append coordlist (list (list "UserPt" userpt nil)))) ; Add user point with nil for blocktype

            ; Draw polyline from collected points
            ;(command "._PLINE")
            ;(foreach pt coordlist
            ;    (command (cadr pt))) ; Directly use the coordinates
            ;(command "")

            ; Print the coordlist
            (princ "\nBlock Coordinates and Names: ") (princ coordlist)
        )
        (princ "\nNo blocks selected.")
    )
    (princ)
)

Output example:
Block Coordinates and Names: ((123abc2_BLOCK (3234.71 331.41 32.0) nil) (abcxyde19_BLOCK (3294.71 435.333 32.0) Arc) (123abc1_BLOCK (3341.36 460.529 32.0) nil) (abcxyde20_BLOCK (3461.36 460.529 32.0) Arc) (123abc3_BLOCK (3501.36 500.529 32.0) nil) (UserPt (3501.36 620.529 32.0) nil))