AutoLISP count polylines and sum the quantity of them SORTED by linetype

Viewed 274

This code here lists every polyline and their linetype to the command line one by one.

Is there a way to sum up the same linetype polylines and get a final result like:

X linetype : 5 piece Y linetype : 2 piece Z linetype : 8 piece

(defun c:TEST (/ ss i obj)
  (setvar "cmdecho" 0)
  (if
    (setq ss (ssget  '((0 . "*POLYLINE,LINE"))))
    (repeat (setq i (sslength ss))
    (setq obj (vlax-ename->vla-object (ssname ss (setq i (1- i)))))
    (prompt (strcat "\nLe type de ligne est\n" (vla-get-Linetype  obj)))
      )
    )
  (setvar "cmdecho" 1)
  (princ)

)
2 Answers

Yes, just create a little function for yourself,

(defun incr (key tbl)
  (cond
    ((null tbl) 
       ;; no key in tbl - create new entry
       ;; with the count of 1
      (list (cons key 1)))
    ((= key (caar tbl)) 
       ;; key is in the car of tbl -- increment the count
      (cons (cons key (+ 1 (cdar tbl)))
            (cdr tbl)))
    (T ;; key is in the cdr of tbl -- keep on searching
       ;; while preserving this entry, in the car
      (cons (car tbl)
        (incr key (cdr tbl))))))

Now we can use it,

(defun c:TEST (/ ss i obj key tbl)
  
  (if (setq ss (ssget  '((0 . "*POLYLINE,LINE"))))
    (repeat (setq i (sslength ss))
      (setq obj (vlax-ename->vla-object (ssname ss (setq i (1- i)))))
      ;;  here:
      (setq key (vla-get-Linetype obj))
      (setq tbl (incr key tbl))))
      
  tbl)

In developing the incr function we followed the principle of "correctness first, efficiency later" i.e. we first write the simplest code which does the job. In particular, if each of your N polylines will have a different linetype, the use of this version of incr will contribute the time quadratic in N to the total execution time.

I would suggest the use of an association list, constructed in the same manner as the counter used as part of my Block Counter tutorial.

You can implement this in the following way:

(defun c:test ( / a i l s x )
    (if (setq s (ssget '((0 . "LINE,POLYLINE"))))
        (repeat (setq i (sslength s))
            (if (setq i (1- i)
                      x (cond ((cdr (assoc 6 (entget (ssname s i))))) ("BYLAYER"))
                      a (assoc x l)
                )
                (setq l (subst (cons x (1+ (cdr a))) a l))
                (setq l (cons  (cons x 1) l))
            )
        )
    )
    l
)

A couple of additional points to note:

  • You don't necessarily need to turn to ActiveX - the object linetype is held by DXF group 6 in the DXF data, else the linetype is set to ByLayer if this group is absent.
  • There is no need to alter the setting of the CMDECHO system variable, as we're not calling any standard AutoCAD commands whose output would need to be suppressed.
Related