LISP Request - Block Count Inside a Closed Polyline

LISP Request - Block Count Inside a Closed Polyline

Anonymous
Not applicable
16,141 Views
81 Replies
Message 1 of 82

LISP Request - Block Count Inside a Closed Polyline

Anonymous
Not applicable

Hi CAD Friends,

 

Wonder if there is a LISP routine (already created by someone) to count all the blocks inside a closed polyline.

 

These are typically plant blocks with attributes in it. I have these sheet layout boundaries in model space, and the City now wants the count of all the plant blocks in a particular sheet, and a totals count in the end. I was using BCOUNT, but then I have to select the blocks individually along the sheet boundaries carefully. Instead of that If I can select the polylines of these sheet boundaries, then the lisp should count and provide a total count of different types of blocks contained (all the blocks with the centre point inside that selected polyline) inside the closed polyline. 

 

If some one can modify the BCOUNT lisp adding an additional feature to count blocks inside the user selected closed polyline ( get input from user selecting the closed polyline), that would be awesome.

 

Regards,

 

VA

0 Likes
16,142 Views
81 Replies
Replies (81)
Message 2 of 82

Kent1Cooper
Consultant
Consultant

If the outlines are always rectangular and orthogonal, I can imagine a way to do it.  Would that be the case?  It would involve getting the bounding box of the rectangle, finding all Blocks, and stepping through that selection, checking whether the X and Y coordinate values of each one's insertion point fall between those of the bounding box corners.

 

[There are routines out there to find everything contained within a selected Polyline boundary, but I think they would find only things fully  within, which it doesn't seem would do what you want, since some of yours with their insertion points  inside a boundary extend partly outside it elsewhere.]

Kent Cooper, AIA
0 Likes
Message 3 of 82

Anonymous
Not applicable

Hi Kent1Cooper,

 

Thanks for taking on my request.

 

Yes. The programming logic came across my mind was exactly what you pointed out.

 

As you mentioned the sheet viewport boundary polylines will not be clean rectangles. It could be irregular shapes depending upon the viewport outlines. Will that be a problem? If I understand you correctly, the issue here is how to register the irregular shape inside  the model space. Will it work the way we use AREA command by selecting a polyline and Autocad makes a hatch or shade in that area showing it is registered. Just a wild thought.

 

Please let me know if you need more details in this regard.

 

Thanks for your time,

 

VA

0 Likes
Message 4 of 82

maratovich
Advisor
Advisor

Your example is not the way you write.
Attach a real example.

---------------------------------------------------------------------
Software development
Automatic creation layouts and viewport. Batch printing drawings from model.
www.kdmsoft.net
0 Likes
Message 5 of 82

DannyNL
Advisor
Advisor

Can probably still use some finetuning, but try the code below.

 

It will count all blocks with a crossing polygon on the selected closed polyline. All polyline segments (line or arc) will be divided into 10 straight segments and this is controlled by the precision variable. So the code could still be optimized to use one segment for line segments and maybe more than 10 for arc segments. But is is a start.

 

Blocks will be counted and reported into the command line/text screen.

 

(defun c:Test (/ T_Selection T_Object T_Precision T_Position T_PointList T_BlockName T_BlockList)
   (if
      (and
         (setq T_Selection (ssget ":S+." '((0 . "*POLYLINE"))))
         (setq T_Object (vlax-ename->vla-object (ssname T_Selection 0)))
         (vlax-Curve-isClosed T_Object)
         (vlax-Curve-isPlanar T_Object)
      )
      (progn
         (setq T_Precision 0.1)
         (setq T_Position  0.0)
         (while
            (<= T_Position (vlax-Curve-GetEndParam T_Object))
            (setq T_PointList (append T_PointList (list (vlax-Curve-GetPointAtParam T_Object T_Position))))
            (setq T_Position (+ T_Position T_Precision))
         )
         (if
            (and
               T_PointList
               (setq T_Selection (ssget "_CP" T_PointList '((0 . "INSERT"))))
            )
            (progn
               (foreach T_Entity (vl-remove-if '(lambda (T_Item) (listp (cadr T_Item))) (ssnamex T_Selection))
                  (setq T_Object (vlax-ename->vla-object (cadr T_Entity)))
                  (if
                     (not (assoc (setq T_BlockName (vla-get-EffectiveName T_Object)) T_BlockList))
                     (setq T_BlockList (append T_BlockList (list (list T_BlockName 1))))
                     (setq T_BlockList (subst  (list T_BlockName (1+ (cadr (assoc T_BlockName T_BlockList)))) (assoc T_BlockName T_BlockList) T_BlockList))
                  )
               )
               (princ (strcat "\n ** Total number of blocks found: " (itoa (sslength T_Selection)) "\n"))
               (foreach T_Item (vl-sort T_BlockList '(lambda (T_Block1 T_Block2) (< (car T_Block1) (car T_Block2))))
                  (princ (strcat "\n" (car T_Item) ": " (itoa (cadr T_Item))))
               )                              
            )
         )
      )
   )
   (princ)
)
0 Likes
Message 6 of 82

Anonymous
Not applicable

Hi Maratovich,

 

Not sure what you are asking here. The right portion of drawing attached is just a file created to show some blocks  and  the polyline boundaries. The left portion is some sample blocks. The tables are the block counts created using the lisp COUNT (courtesy to Lee-Mac Programing). Please let me know if this does not clear your confusion.

 

Regards,

 

VM

0 Likes
Message 7 of 82

maratovich
Advisor
Advisor
Accepted solution

You'd better turn to Lee-Mac
He will be happy to help you, and will redo the code.

http://www.lee-mac.com/

---------------------------------------------------------------------
Software development
Automatic creation layouts and viewport. Batch printing drawings from model.
www.kdmsoft.net
0 Likes
Message 8 of 82

Anonymous
Not applicable

Hi DannyNL,

 

Thanks for your time and effort for helping me and the CAD community,

I checked briefly the lisp and the lisp counts the blocks inside by clicking the boundary polyline option, As you mentioned it is a great start.

One thing I noticed is that when the boundary polyline cuts a block( even if the insertion point of the block is outside the polyline) the block is still getting counted, which should not be the case.

Let's be optimistic that if someone can find a solution for this .

 

Thanks and regards,

 

VA

0 Likes
Message 9 of 82

DannyNL
Advisor
Advisor

Hi Vince,

 

It was indeed a start. The selection uses a crossing to select the blocks, so even if the block only touches the polyline it will be selected independent of the insertion point. But I've made some changes and hopefully this will be the one that solves your question.

 

AutoCAD doesn't let you select objects based on the insertion point with a crossing or window selection, but only on visible objects. To overcome this problem I'm checking the insertion point of each block, create a point object on that point and then check if this point object is within the polyline boundary with a window polygon selection. Only if it is it will count the block.

 

Please check the code below.

There is one limitation at this point; the block has to be partly within or touching the polyline else the block will not be counted even if the insertion point is within the polyline boundary.

 

(defun c:Test (/ T_Selection T_Entity T_Precision T_Position T_PointList T_BoundaryCheck T_BlockName T_BlockList)
   (if
      (and
         (princ "\nSelect polyline: ")
         (setq T_Selection (ssget ":S+." '((0 . "*POLYLINE"))))
         (setq T_Object (vlax-ename->vla-object (ssname T_Selection 0)))
         (vlax-Curve-isClosed T_Object)
         (vlax-Curve-isPlanar T_Object)
      )
      (progn
         (setq T_Precision 0.1)
         (setq T_Position  0.0)
         (while
            (<= T_Position (vlax-Curve-GetEndParam T_Object))
            (setq T_PointList (append T_PointList (list (vlax-Curve-GetPointAtParam T_Object T_Position))))
            (setq T_Position (+ T_Position T_Precision))
         )
         (if
            (and
               T_PointList
               (setq T_Selection (ssget "_CP" T_PointList '((0 . "INSERT"))))
            )
            (progn
               (foreach T_Entity (vl-remove-if '(lambda (T_Item) (listp (cadr T_Item))) (ssnamex T_Selection))
                  (setq T_Entity (cadr T_Entity))
                  (command "._POINT" "_None" (cdr (assoc 10 (entget T_Entity))))
                  (if
                     (and
                        (setq T_BoundaryCheck (ssget "_WP" T_PointList '((0 . "POINT"))))
                        (ssmemb (entlast) T_BoundaryCheck)
                     )
                     (progn
                        (if
                           (not (assoc (setq T_BlockName (cdr (assoc 2 (entget T_Entity)))) T_BlockList))
                           (setq T_BlockList (append T_BlockList (list (list T_BlockName 1))))
                           (setq T_BlockList (subst  (list T_BlockName (1+ (cadr (assoc T_BlockName T_BlockList)))) (assoc T_BlockName T_BlockList) T_BlockList))
                        )
                     )
                     (ssdel T_Entity T_Selection)
                  )
                  (entdel (entlast))
               )
               (princ (strcat "\n ** Total number of blocks found: " (itoa (sslength T_Selection)) "\n"))
               (foreach T_Item (vl-sort T_BlockList '(lambda (T_Block1 T_Block2) (< (car T_Block1) (car T_Block2))))
                  (princ (strcat "\n" (car T_Item) ": " (itoa (cadr T_Item))))
               )
            )
         )
      )
   )
   (princ)
)
0 Likes
Message 10 of 82

DannyNL
Advisor
Advisor

Just checked my code to your example drawing and it doesn't seem to find the blocks.

Not sure why yet, but I'll try to figure it out and hopefully get back again with a modification.

0 Likes
Message 11 of 82

DannyNL
Advisor
Advisor

Ok, new code.

 

Problem was caused when PDMODE was set to 1 as that makes POINT's invisible and in that case they cannot be selected.

Removed the COMMAND for creating the POINT and changed that to ENTMAKE to speed it up a bit more. And also added a progress bar during the count as it will take some time to count the blocks on your test drawing. Now you know it is still busy.

 

(defun c:Test (/ T_OldPdmode T_Selection T_Entity T_Precision T_Position T_PointList T_Count T_BoundaryCheck T_BlockName T_BlockList)
   (setq T_OldPdmode (getvar "PDMODE"))
   (setvar "PDMODE" 0)      
   (if
      (and
         (princ "\nSelect polyline: ")
         (setq T_Selection (ssget ":S+." '((0 . "*POLYLINE"))))
         (setq T_Object (vlax-ename->vla-object (ssname T_Selection 0)))
         (vlax-Curve-isClosed T_Object)
         (vlax-Curve-isPlanar T_Object)
      )
      (progn
         (setq T_Precision 0.1)
         (setq T_Position  0.0)
         (while
            (<= T_Position (vlax-Curve-GetEndParam T_Object))
            (setq T_PointList (append T_PointList (list (vlax-Curve-GetPointAtParam T_Object T_Position))))
            (setq T_Position (+ T_Position T_Precision))
         )
         (if
            (and
               T_PointList
               (setq T_Selection (ssget "_CP" T_PointList '((0 . "INSERT"))))
            )
            (progn
               (acet-ui-progress "Counting" (sslength T_Selection))
               (setq T_Count 0)
               (foreach T_Entity (vl-remove-if '(lambda (T_Item) (listp (cadr T_Item))) (ssnamex T_Selection))
                  (acet-ui-progress (setq T_Count (1+ T_Count)))
                  (setq T_Entity (cadr T_Entity))
                  (entmake (list '(0 . "POINT") (assoc 10 (entget T_Entity))))
                  (if
                     (and
                        (setq T_BoundaryCheck (ssget "_WP" T_PointList '((0 . "POINT"))))
                        (ssmemb (entlast) T_BoundaryCheck)
                     )
                     (progn
                        (if
                           (not (assoc (setq T_BlockName (cdr (assoc 2 (entget T_Entity)))) T_BlockList))
                           (setq T_BlockList (append T_BlockList (list (list T_BlockName 1))))
                           (setq T_BlockList (subst  (list T_BlockName (1+ (cadr (assoc T_BlockName T_BlockList)))) (assoc T_BlockName T_BlockList) T_BlockList))
                        )
                     )
                     (ssdel T_Entity T_Selection)
                  )
                  (entdel (entlast))
               )
               (acet-ui-progress)
               (princ (strcat "\n ** Total number of blocks found: " (itoa (sslength T_Selection)) "\n"))
               (foreach T_Item (vl-sort T_BlockList '(lambda (T_Block1 T_Block2) (< (car T_Block1) (car T_Block2))))
                  (princ (strcat "\n" (car T_Item) ": " (itoa (cadr T_Item))))
               )
               (princ "\n")
            )
         )
      )
   )
   (setvar "PDMODE" T_OldPdmode)
   (princ)
)
Message 12 of 82

ВeekeeCZ
Consultant
Consultant
Accepted solution

It works to me... but it takes time.......

 

This quickie uses Lee's sub and Danny's part for block counting (hope you don't mind). Its a bit faster.

 

(defun c:BCountIn ( / pl ss i T_BlockName T_Entity T_BlockList T_Item T_BlockCounter)

  (if (and (setq pl (car (entsel "\nPolyline: ")))
           (setq ss (ssget "_X" (list '(0 . "INSERT") (cons 410 (getvar 'CTAB)))))
           (setq T_BlockCounter 0))
    (progn
      (repeat (setq i (sslength ss))
        (if (LM:Inside-p (cdr (assoc 10 (entget (setq T_Entity (ssname ss (setq i (1- i))))))) pl)
          (setq T_BlockCounter (1+ T_BlockCounter)
                T_BlockList (if (not (assoc (setq T_BlockName (cdr (assoc 2 (entget T_Entity)))) T_BlockList))
                              (append T_BlockList (list (list T_BlockName 1)))
                              (subst  (list T_BlockName (1+ (cadr (assoc T_BlockName T_BlockList)))) (assoc T_BlockName T_BlockList) T_BlockList)))))
      (if T_BlockList
        (progn
          (princ (strcat "\n ** Total number of blocks found: " (itoa T_BlockCounter) "\n"))
          (foreach T_Item (vl-sort T_BlockList '(lambda (T_Block1 T_Block2) (< (car T_Block1) (car T_Block2))))
            (princ (strcat "\n" (car T_Item) ": " (itoa (cadr T_Item)))))))))
  (princ)
)
        



  ; Lee Mac Point Inside the Polyline
  (defun LM:Inside-p ( pt ent / _GroupByNum lst nrm obj tmp )

    (defun *error* (errmsg)
      (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
        (princ (strcat "\nError: " errmsg)))
      (vla-put-color obj acYellow)
      (princ))
    
    
    (defun _GroupByNum ( l n / r)
      (if l
        (cons (reverse (repeat n (setq r (cons (car l) r) l (cdr l)) r))
              (_GroupByNum l n))))
    
    (if (= (type ent) 'VLA-OBJECT)
      (setq obj ent
            ent (vlax-vla-object->ename ent))
      (setq obj (vlax-ename->vla-object ent)))
    
    (setq lst (_GroupByNum (vlax-invoke (setq tmp (vlax-ename->vla-object (entmakex (list
                                                                                      (cons 0 "RAY")
                                                                                      (cons 100 "AcDbEntity")
                                                                                      (cons 100 "AcDbRay")
                                                                                      (cons 10 pt)
                                                                                      (cons 11 (trans '(1. 0. 0.) ent 0))))))
                             'IntersectWith obj acextendnone) 3 ))
    (vla-delete tmp)
    (setq nrm (cdr (assoc 210 (entget ent))))
    
    ;; gile:
    (and lst (not (vlax-curve-getparamatpoint ent pt))
         (= 1 (rem (length (vl-remove-if (function (lambda ( p / pa p- p+ p0 s1 s2 )
                                                     (setq pa (vlax-curve-getparamatpoint ent p))
                                                     (or (and (equal (fix (+ pa (if (minusp pa) -0.5 0.5))) pa 1e-8)
                                                              (setq p- (cond ((setq p- (vlax-curve-getPointatParam ent (- pa 1e-8)))
                                                                              (trans p- 0 nrm))
                                                                             ((trans (vlax-curve-getPointatParam ent (- (vlax-curve-getEndParam ent) 1e-8)) 0 nrm))))
                                                              (setq p+ (cond ((setq p+ (vlax-curve-getPointatParam ent (+ pa 1e-8)))
                                                                              (trans p+ 0 nrm))
                                                                             ((trans (vlax-curve-getPointatParam ent (+ (vlax-curve-getStartParam ent) 1e-8)) 0 nrm))))
                                                              (setq p0 (trans pt 0 nrm))
                                                              (<= 0 (* (sin (angle p0 p-)) (sin (angle p0 p+)))) ;; LM Mod
                                                              )
                                                         (and (/= 0. (vla-getBulge obj (fix pa)))
                                                           (equal '(0. 0.)
                                                                  (cdr (trans (vlax-curve-getFirstDeriv ent pa) 0 nrm)) 1e-9)))))
                             lst
                             ))
                   2))))
Message 13 of 82

DannyNL
Advisor
Advisor

I don't mind at all Smiley Happy

I've found the counting to be a bit slow myself and are already making changes to eliminate to multiple SSGET's needed as this is causing the slow processing I assume.

 

But looking at the code you posted; well, I don't have my wizard degree yet, so I'll need to take my time to understand completely how it works Smiley Wink

0 Likes
Message 14 of 82

ВeekeeCZ
Consultant
Consultant

@DannyNL wrote:

 

...

But looking at the code you posted; well, I don't have my wizard degree yet, so I'll need to take my time to understand completely how it works Smiley Wink


Don't get me wrong, I just have a general awareness about the principle and this sub saved in my archive.

 

HERE is the original link to the routine, HERE is wiki site about Ray casting algorithm. 

 

All the credits to @Lee_Mac and @_gile.

 

Message 15 of 82

DannyNL
Advisor
Advisor

Way better and faster than my method of using POINT objects.

So changed my code to use ray casting as well.

 

To select all blocks inside the polyline, remove the semicolon before (sssetfirst.....)

 

(defun c:Test (/ T_OldPdmode T_Selection T_Entity T_LowerLeft T_UpperRight T_Precision T_Position T_PointList T_Count T_EntityList T_CheckLine T_IntersectPoints T_BoundaryCheck T_BlockName T_BlockList)  
   (if
      (and
         (princ "\nSelect polyline: ")
         (setq T_Selection (ssget ":S+." '((0 . "*POLYLINE"))))
         (setq T_Object (vlax-ename->vla-object (ssname T_Selection 0)))
         (vlax-Curve-isClosed T_Object)
         (vlax-Curve-isPlanar T_Object)
      )
      (progn
         (setq T_Precision 0.1)
         (setq T_Position  0.0)
         (while
            (<= T_Position (vlax-Curve-GetEndParam T_Object))
            (setq T_PointList (append T_PointList (list (vlax-Curve-GetPointAtParam T_Object T_Position))))
            (setq T_Position (+ T_Position T_Precision))
         )
         (if
            (and
               T_PointList
               (setq T_Selection (ssget "_CP" T_PointList '((0 . "INSERT"))))
            )
            (progn
               (acet-ui-progress "Counting" (sslength T_Selection))
               (setq T_Count 0)
               (foreach T_Entity (vl-remove-if '(lambda (T_Item) (listp (cadr T_Item))) (ssnamex T_Selection))
                  (acet-ui-progress (setq T_Count (1+ T_Count)))
                  (setq T_EntityList (entget (setq T_Entity (cadr T_Entity))))                  
                  (if
                     (and
                        (setq T_CheckLine (entmakex (list '(0 . "RAY") '(100 . "AcDbEntity") '(100 . "AcDbRay") (assoc 10 T_EntityList)(cons 11 (mapcar '- (vlax-curve-GetClosestPointTo T_Object (cdr (assoc 10 T_EntityList))) (cdr (assoc 10 T_EntityList)))))))
                        (not (vl-catch-all-error-p (setq T_IntersectPoints (vl-catch-all-apply 'vlax-safearray->list (list (vlax-variant-value (vla-IntersectWith (vlax-ename->vla-object T_CheckLine) T_Object acExtendNone)))))))
                        (= (rem (length (_GroupByNum T_IntersectPoints 3)) 2) 1)
                     )
                     (progn
                        (if
                           (not (assoc (setq T_BlockName (cdr (assoc 2 T_EntityList))) T_BlockList))
                           (setq T_BlockList (cons  (list T_BlockName 1) T_BlockList))
                           (setq T_BlockList (subst (list T_BlockName (1+ (cadr (assoc T_BlockName T_BlockList)))) (assoc T_BlockName T_BlockList) T_BlockList))
                        )                        
                     )
                     (ssdel T_Entity T_Selection)                                             
                  )
                  (if T_CheckLine (entdel T_CheckLine))
               )
               ;(sssetfirst nil T_Selection)
               (acet-ui-progress)
               (princ (strcat "\n ** Total number of blocks found: " (itoa (sslength T_Selection)) "\n"))
               (foreach T_Item (vl-sort T_BlockList '(lambda (T_Block1 T_Block2) (< (car T_Block1) (car T_Block2))))
                  (princ (strcat "\n" (car T_Item) ": " (itoa (cadr T_Item))))
               )
               (princ "\n")
            )
         )
      )
   )
   (princ)
)


; By Lee Mac
(defun _GroupByNum (l n / r)
   (if
      l
      (cons (reverse (repeat n (setq r (cons (car l) r) l (cdr l)) r)) (_GroupByNum l n))
   )
)
0 Likes
Message 16 of 82

Kent1Cooper
Consultant
Consultant

This may overlap with suggestions already made here, but there are routines out there to determine whether a location  [XY coordinates] is inside a Polyline of any shape, with various approaches, such as this one.  Could you find all Blocks, extract their insertion points, and check those insertion points on their own for whether they're inside, using a routine such as that, rather than working with the Blocks themselves?  That particular routine's approach may take some time with a large number of Blocks, but it looks to me like it would be viable, and wouldn't have the problems some suggestions here have [e.g. with Blocks whose insertion points are outside but whose contents extend inside].

Kent Cooper, AIA
0 Likes
Message 17 of 82

Anonymous
Not applicable

Hi DannyNL, BeeKeeCZ and Kent1Cooper,

Thank you all very much for helping me out. I have done some preliminary tests on the routine provided. The code is awesome and it was counting all the blocks the way I was requesting. But when I made a polyline with an irregular shape (the white polyline in the drawing) The lisp routines are giving different results. I tried it with BCOUNT and TEST. TEST is not counting 4 trees inside that irregular polyline shape. Since I am not a programming person, I could not figure out why it is not being counted.

 

I haven't tried this on a real project yet ( sorry, so busy with meetings and conferences in new year). I will let you know as soon as I can. Please give me a few days.

 

Regards,

 

VA

0 Likes
Message 18 of 82

cadffm
Consultant
Consultant

... not counting THREE trees, or?

 

Because thats only a simple example to show how you could program a function, it is not e perfect function to sell or to commercially use it with important data.

 

Which does not consider all important points for such a routine.

Because of the 3 objects - a simple check is performed:
Line from base point to outside, Question: How often does this line intersect the polygon?
The problem: The line runs directly through a vertex(1) of the polyline and again "right" through a polygon segment,
So the polygon was cut twice through the line and therefore it is assumed the base point must be outside.

Here is the lack of control if a vertex was cut or not, so the result is wrong.

But there is more:
The AutoCAD object selection depends on the view depending on the mode, so the result may vary depending on the view.
For this kind of routine it has to be ensured that the current view is "good" when using ssget-cp.

Another problem that may arise in rarer cases are the arc segments,
for object selection these are assumed to be many small line segments.
Depending on the length of the bow, the inaccuracy varies here
The block base point could therefore lie between the imaginary lines and the actual arc segment.

Sebastian

0 Likes
Message 19 of 82

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

....  Could you find all Blocks, extract their insertion points, and check those insertion points on their own for whether they're inside, using a routine such as that, rather than working with the Blocks themselves?  That particular routine's approach may take some time with a large number of Blocks....


That routine's method is to temporarily Offset the boundary object Through the desired point, and compare the area of the result with that of the selected boundary.  Doing that kind of thing narrowed down to your particular sitution comes out like this [lightly tested and without the usual controls yet]:

(defun C:BIB ; = Blocks Inside Boundary
  (/ bndry reflen blks n blk)
  (setq
    bndry (car (entsel "\nBoundary object: "))
    reflen (vlax-curve-getDistAtParam bndry (vlax-curve-getEndParam bndry))
    blks (ssget "_X" (list '(0 . "INSERT") (cons 410 (getvar 'ctab))))
    insiders (ssadd); initially empty
  ); setq
  (repeat (setq n (sslength blks))
    (command "_.offset" "_through" bndry
      "_none" (cdr (assoc 10 (entget (setq blk (ssname blks (setq n (1- n)))))))
      ""
    ); command
    (if (< (vlax-curve-getDistAtParam (entlast) (vlax-curve-getEndParam (entlast))) reflen)
      (ssadd blk insiders); put it in the selection
    ); if
    (command "_.u"); Undo Offset
  ); repeat
  (princ)
); defun

 

It took about 15 seconds to do any rectangle in your sample drawing [it shouldn't matter which, since it compares the area of something Offset through the insertion point of every  Block in the current space to whatever boundary was selected].  I tried it successfully with some Blocks partially outside but their insertion points inside, and vice versa, and with a Circle as a boundary, and with a more convoluted-shaped Polyline.

 

It simply puts the ones whose insertion points are inside the boundary into the non-localized "insiders" selection set.  It could put them into a list if that's easier to work with.  Processing the result for Block count, table input, etc., would be in addition to what this much does.

Kent Cooper, AIA
0 Likes
Message 20 of 82

ВeekeeCZ
Consultant
Consultant

@Anonymous wrote:

Hi DannyNL, BeeKeeCZ and Kent1Cooper,

Thank you all very much for helping me out. I have done some preliminary tests on the routine provided. The code is awesome and it was counting all the blocks the way I was requesting. But when I made a polyline with an irregular shape (the white polyline in the drawing) The lisp routines are giving different results. I tried it with BCOUNT and TEST. TEST is not counting 4 trees inside that irregular polyline shape. Since I am not a programming person, I could not figure out why it is not being counted.

 

...

The routine from post #12 gives you a correct result, the same as BCOUNT. And fast enough. 

0 Likes