Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LISP Request - Block Count Inside a Closed Polyline

81 REPLIES 81
SOLVED
Reply
Message 1 of 82
Anonymous
12638 Views, 81 Replies

LISP Request - Block Count Inside a Closed Polyline

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

81 REPLIES 81
Message 41 of 82
Anonymous
in reply to: john.uhden

Hi John.Uhden,

 

This routine is working great. it actually counts all the blocks correctly in all the tests i did so far.
I have a few suggestions, in order to make this little user friendly.

 

1. After the BIB function is called, is there a possibility of showing a drop down list in the command line with all the block names in the current drawing,
incase if we want to select a particular block to count inside the selected polyline?

 

2. Once the routine is run ( result: when all the blocks inside the polyline are selected),
can we subsequently run the BCOUNT lisp routine ( courtesy to Lee-MAC programming) , so that we can get the counts of all the blocks in the command line itself? Now I am doing it as two different lisp runs, BIB and then BCOUNT.


3. being next step , Is there a way to extract the key attribute values in the plant blocks, A, B or a,b or aa, bb  and get the counts of each type of blocks in a table showing :
   First column:  Key value ( eg: A,B or a,b or aa, bb depending upon how many blocks in the selection inside selected polyline)
   Second column: Name of Block: (eg: Tree-Dec-Prairie Spire Green Ash)
   Third Column: Total counts of each block

 

4. The routine should ask for an insertion point for the table, and the table should have Title ( Plant Count) and Headers - Column 1: Attribute Key ; Column 2: Block Name; and Column 3: Block Counts

 

5.  The table items should be sorted by column 1: Attribute Key - A-Z; then a-z; and then aa-zz.

Not sure every thing listed here is attainable as suggested. This way the LISP will be a more robust one.

 

Thanks for all your help. This is really working good so far. Please let me know if you need any more details. I have attached the drawing for your use.

Regards,

VA

Message 42 of 82
john.uhden
in reply to: Anonymous

I'm glad that the routine will be helpful to you.

 

!.  The routine allows you to type in one or more block names with wildcards, separated by commas.  As freeware, I am not going to complicate the code with multiple-select dialog boxes.

 

2.  Yes, I could add reporting of the number of insertions for each block name it finds within the boundary.  I will do so.

 

3.  Someone else can add the attribute reporting.  Everything here is public domain.

 

4.  I am not table capable since all I have is ACAD 2002.  But someone else could add that.

 

5.  Same as #4.

 

6.  I should add ellipses as candidate boundaries.  No, I am not adding polyface meshes or hatches or images or 3D solids or Civil 3D surfaces.

John F. Uhden

Message 43 of 82
john.uhden
in reply to: john.uhden

Here ya go...

 

(defun C:BlocksInsideBoundary ( / *error* cmdecho @Inside @delta @addname bnames Oname SS i B E Object P Names)
  ;; v1.0 (c. 08-20-03)
  ;; v1.1 (09-15-03) using Uhden's new @Inside function
;; v2.0 donated to AutoCAD forum (01-09-18) (gc) (vl-load-com) (or *acad* (setq *acad* (vlax-get-acad-object))) (or *doc* (setq *doc* (vla-get-ActiveDocument *acad*))) (defun *error* (error) (if (vl-position cmdecho '(0 1))(setvar "cmdecho" cmdecho)) (if B (redraw B 4)) (vla-endundomark *doc*) (cond ((not error)) ((wcmatch (strcase error) "*QUIT*,*CANCEL*")) (1 (princ (strcat "\nERROR: " error))) ) (princ) ) (vla-endundomark *doc*) (vla-startundomark *doc*) (setq cmdecho (getvar "cmdecho")) (setvar "cmdecho" 0) (command "_.expert" (getvar "expert")) ;; dummy command ;;--------------------------------------------------------------------------------------------- ;; Function to determine if a point is inside a curve boundary (defun @Inside (PIQ Object / Closest Start End Param P a1 a2 Defl @2D @Bulge) ;; "LOOK, MA'... NO RAYS!" ;; @Inside.lsp v1.0 (09-15-03) John F. Uhden, Cadlantic. ;; v2.0 Revised (09-17-03) - See notes below. ;; v3.0 Revised (09-20-03) - See notes below. ;; Function to determine whether a point is inside the boundary ;; of a closed curve. ;; It employs the theorem that the sum of the deflections of a ;; point inside the curve should equal 360°, and if outside 0° ;; (both absolute values). ;; The results with Ellipses were fairly rough, and the results ;; with a Spline were very rough, thus the fuzz factor of 2. ;; ;; Arguments: ;; PIQ - Point to test (2D or 3D point as a list in UCS) ;; Object - Curve to test (Ename or VLA-Object) ;; ;; Returns: ;; T (if the PIQ is inside the curve) ;; nil (if either the arguments are invalid, ;; or the PIQ is on or outside the curve) ;; ;; NOTES: ;; Requires one or another version of the @delta function, ;; such as included here. ;; It will not work well with self-intersecting (overlapping) ;; bulged polyline segments. ;; Curves can be CIRCLEs, ELLIPSEs, LWPOLYLINEs, POLYLINES, ;; SPLINEs, and maybe even more. ;; Thanks already to Doug Broad for finding bugs. (setq Sample 0.5) ; this is better for bulged polylines. ;; Sure, you could decrease the sampling from 0.5 to say 0.1, ;; but it will only slow down the process and still not ;; guarantee success with overlapping bulged segments. ;; DO NOT change the sampling value to anything that is ;; greater than 1 or not evenly divisible into 1, as you ;; would not be sampling vertices. ;; (09-17-03) Found that cusps brought back inside the figure ;; yield a total deflection of (* pi 2), so changed evaluation ;; to see if deflection was greater than 4, which is ;; equivalent to a fuzz factor of 2.28 from (* pi 2). (vl-load-com) (defun @delta (a1 a2) (cond ((> a1 (+ a2 pi)) (+ a2 pi pi (- a1)) ) ((> a2 (+ a1 pi)) (- a2 a1 pi pi) ) (1 (- a2 a1)) ) ) ;; Function to convert a 3D point into 2D for the purpose ;; of ignoring the Z value. ;; Added (09-20-03) (defun @2D (p)(list (car p)(cadr p))) ;;----------------------------------------------------- ;; Function to determine if an angle is with the sector ;; defined by two other angles. ;; Returns the delta angle from the first angle. ;; (defun @insect (Ang Ba Ea) (if (> Ba Ea) (cond ((>= Ang Ba)) ((<= Ang Ea)) (1 nil) ) (< Ba Ang Ea) ) ) (defun @Bulge (Param / Bulge V1 V2 Half Delta Chord Radius Center Ba Ea Ang P) (and (setq Bulge (vl-catch-all-apply 'vla-getbulge (list Object (fix Param)))) (numberp Bulge) (/= Bulge 0) (< Param End) (setq V1 (vlax-curve-getpointatparam Object (fix Param))) (setq V2 (vlax-curve-getpointatparam Object (1+ (fix Param)))) (setq V1 (trans V1 0 1)) (setq V2 (trans V2 0 1)) (setq Half (if (minusp Bulge) -0.5 0.5) Delta (* 4.0 (atan (abs Bulge))) Chord (distance V1 V2) Radius (/ Chord 2 (sin (/ Delta 2))) Center (polar V1 (+ (angle V1 V2)(* (- pi Delta) Half)) Radius) ) (if (minusp Bulge) (setq Ba (angle Center V2) Ea (angle Center V1)) (setq Ba (angle Center V1) Ea (angle Center V2)) ) (setq Ang (angle Center PIQ)) (@insect Ang Ba Ea) (setq P (polar Center Ang Radius)) ) P ) (and (cond ((not Object) (prompt " No object provided.") ) ((= (type Object) 'VLA-Object)) ((= (type Object) 'Ename) (setq Object (vlax-ename->vla-object Object)) ) (1 (prompt " Improper object type.")) ) (or (and (< 1 (vl-list-length PIQ) 4) (vl-every 'numberp PIQ) ) (prompt " Improper point value.") ) (or (not (vl-catch-all-error-p (setq Start (vl-catch-all-apply 'vlax-curve-getStartPoint (list Object) ) ) ) ) (prompt " Object is not a curve.") ) (or (equal Start (vlax-curve-getendpoint Object) 1e-10) (prompt " Curve is not closed.") ) (setq P (trans PIQ 1 0)) ; PIQ in WCS (setq Closest (vlax-curve-getclosestpointto Object P) ; In WCS ) ;; Test to see if PIQ is on object: (not (equal (@2D P)(@2D Closest) 1e-10)) ; in WCS (setq End (vlax-curve-getEndparam Object)) (if (= (vla-get-objectname Object) "AcDbSpline") (setq Sample (/ End 100)) (setq Sample 1.0) ) (setq Param Sample Defl 0.0) (setq a1 (angle PIQ (trans Start 0 1))) ; in UCS (while (<= Param End) (setq Param (min Param End)) (setq P (vlax-curve-getpointatparam Object Param) a2 (angle PIQ (trans P 0 1)) ; in UCS Defl (+ Defl (@delta a1 a2)) a1 a2 ) ; (grdraw PIQ P 3) (if (setq P (@Bulge Param)) (progn ;(grdraw PIQ (trans (vlax-curve-getpointatparam Object P1) 0 1) 1) ;(grdraw PIQ P 1) ;(grdraw PIQ (trans (vlax-curve-getpointatparam Object P2) 0 1) 3) (setq a2 (angle PIQ P) Defl (+ Defl (@delta a1 a2)) a1 a2 ) ) ) (setq Param (+ Param Sample)) ) ;(print Defl) ; Optional display of results (> (abs Defl) 4) ) ) ;;--------------------------------------------------------------------------------------------------------- ;; Function to keep count of block names found inside the boundary (defun @addname (name / item) (if (setq item (assoc name Names)) (setq Names (subst (cons name (1+ (cdr item))) item Names)) (setq Names (cons (cons name 1) Names)) ) ) ;;----------------------------- ;; Begin the action: (and (setq B (car (entsel "\nSelect boundary object: "))) (setq Object (vlax-ename->vla-object B)) (setq Oname (vlax-get Object 'ObjectName)) (cond ((not (vl-position Oname '("AcDbPolyline" "AcDb2dPolyline" "AcDbSpline" "AcDbCircle" "AcDbEllipse"))) (alert (strcat "Object selected is a(n) " Oname)) ) ((and (/= Oname "AcDbCircle")(/= Oname "AcDbEllipse")(= (vlax-get Object 'Closed) 0)) (alert "Object is not closed.") ) ((and (= Oname "AcDbEllipse")(/= (rem (vlax-get Object 'EndAngle) pi)(vlax-get Object 'StartAngle))) (alert "Ellipse is not closed.") ) ((zerop (vlax-get Object 'Area)) (alert "Object has an area of zero (0).") ) (1) ) (or (redraw B 3) 1) (setq bnames (getstring "\nEnter block names to find, or * for all <*>: ")) (or (/= bnames "")(setq bnames "*")) (setq SS (ssget "X" (list '(0 . "INSERT")(cons 2 bnames)(cons 410 (getvar "ctab"))))) (repeat (setq i (sslength SS)) (setq p (cdr (assoc 10 (entget (setq e (ssname SS (setq i (1- i)))))))) (if (@Inside P Object) (@addname (cdr (assoc 2 (entget e)))) (ssdel e SS) ) 1 ) (if (and SS (> (sslength SS) 0)) (progn (princ (strcat "\nFound " (itoa (sslength SS)) " blocks within boundary.")) (sssetfirst nil SS) (foreach name Names (princ (strcat "\n" (car name) ": " (itoa (cdr name))))) ) (alert "No blocks found inside boundary") ) ) (*error* nil) ) (defun C:BIB ()(C:BlocksInsideBoundary))

John F. Uhden

Message 44 of 82
Anonymous
in reply to: john.uhden

Hi John,

 

Thanks for taking time to do the revision. I tested it and it is working fine.

 

Regards,

 

VM

Message 45 of 82
john.uhden
in reply to: Anonymous

I love good news!

John F. Uhden

Message 46 of 82
lando7189
in reply to: Anonymous

As far a a list of blocks... you can easily incorporate one of the GUI functions in DOSLib with just a few lines of code.

Message 47 of 82
DannyNL
in reply to: Anonymous

Actually the spline-turned-into-polyline is recognized correctly, but it is the selection of the blocks that fails due to the huge amount of points used for the crossing polygon. The code below uses the bounding box of the poyline as selection crossing and routine should now work in all cases. Although somewhat slower on those complex polyline shapes due to the increased number of blocks that are selected for checking. Also renamed the command from Test to BlkCounter.

 

I've noticed you've made some additional requests to be added, but I've not looked at those (yet).

 

(defun c:BlkCounter (/ BC_Selection BC_Entity BC_LowerLeft BC_UpperRight BC_PointList BC_Result BC_Previous BC_Count BC_EntityList BC_CheckLine BC_IntersectPoints BC_BoundaryCheck BC_BlockName BC_BlockList)  
   (if
      (and
         (princ "\nSelect polyline: ")
         (setq BC_Selection (ssget ":S+." '((0 . "*POLYLINE"))))
         (setq BC_Object (vlax-ename->vla-object (ssname BC_Selection 0)))
         (vlax-Curve-isClosed BC_Object)
         (vlax-Curve-isPlanar BC_Object)
         (setq BC_PointList (_GetBoundingBox BC_Object))
         (setq BC_Selection (ssget "_CP" BC_PointList '((0 . "INSERT"))))         
      )                         
      (progn
         (acet-ui-progress "Counting" (sslength BC_Selection))
         (setq BC_Count 0)
         (foreach BC_Entity (vl-remove-if '(lambda (BC_Item) (listp (cadr BC_Item))) (ssnamex BC_Selection))
            (acet-ui-progress (setq BC_Count (1+ BC_Count)))
            (setq BC_EntityList (entget (setq BC_Entity (cadr BC_Entity))))
            (if
               (_PointInside (cdr (assoc 10 BC_EntityList)) BC_Object)
               (progn
                  (if
                     (not (assoc (setq BC_BlockName (cdr (assoc 2 BC_EntityList))) BC_BlockList))
                     (setq BC_BlockList (cons  (list BC_BlockName 1) BC_BlockList))
                     (setq BC_BlockList (subst (list BC_BlockName (1+ (cadr (assoc BC_BlockName BC_BlockList)))) (assoc BC_BlockName BC_BlockList) BC_BlockList))
                     )
               )
               (ssdel BC_Entity BC_Selection)
            )
            (if BC_CheckLine (entdel BC_CheckLine))
         )
         ;(sssetfirst nil BC_Selection)
         (acet-ui-progress)
         (princ (strcat "\n ** Total number of blocks found: " (itoa (sslength BC_Selection)) "\n"))
         (foreach BC_Item (vl-sort BC_BlockList '(lambda (BC_Block1 BC_Block2) (< (car BC_Block1) (car BC_Block2))))
            (princ (strcat "\n" (car BC_Item) ": " (itoa (cadr BC_Item))))
         )
         (princ "\n")
      )
   )
   (princ)
)

(defun _GetBoundingBox (GBB_Object / GBB_LowerLeft GBB_UpperRight)
   (if
      (vlax-method-applicable-p GBB_Object 'GetBoundingBox)
      (progn
         (vla-GetBoundingBox GBB_Object 'GBB_LowerLeft 'GBB_UpperRight)
         (setq GBB_LowerLeft  (vlax-safearray->list GBB_LowerLeft))
         (setq GBB_UpperRight (vlax-safearray->list GBB_UpperRight))
         (list
            GBB_LowerLeft
            (list (nth 0 GBB_UpperRight) (nth 1 GBB_LowerLeft) 0.0)
            GBB_UpperRight
            (list (nth 0 GBB_LowerLeft) (nth 1 GBB_UpperRight) 0.0)
         )
      )
   )
)
         

(defun _PointInside (PI_Point PI_PolylineObject / PI_RayAngles PI_ClosestPoint PI_AngleList PI_RefAngle PI_AngleList PI_CheckLine PI_IntersectPoints PI_CheckList)
   (setq PI_RayAngles (_AngleList 12))
   (setq PI_ClosestPoint (vlax-curve-GetClosestPointTo PI_PolylineObject PI_Point))
   (setq PI_AngleList (mapcar '(lambda (PI_Factor) (* pi PI_Factor)) PI_RayAngles))
   (if
      (not (equal (rem (setq PI_RefAngle (angle PI_Point PI_ClosestPoint)) (/ pi 2.0)) 0))
      (setq PI_AngleList (append (mapcar '(lambda (PI_Factor) (+ (* pi PI_Factor) PI_RefAngle )) PI_RayAngles) PI_AngleList))
   )
   (foreach PI_Angle PI_AngleList
      (setq PI_CheckLine (entmakex (list '(0 . "RAY") '(100 . "AcDbEntity") '(100 . "AcDbRay") (cons 10 PI_Point) (cons 11 (mapcar '- (polar PI_Point PI_Angle 5.0) PI_Point)))))
      (if         
         (not (vl-catch-all-error-p (setq PI_IntersectPoints (vl-catch-all-apply 'vlax-safearray->list (list (vlax-variant-value (vla-IntersectWith (vlax-ename->vla-object PI_CheckLine) PI_PolylineObject acExtendNone)))))))
         (setq PI_CheckList (cons (length (_GroupByNum PI_IntersectPoints 3)) PI_CheckList))
         (setq PI_CheckList (cons nil PI_CheckList))
      )
      (entdel PI_CheckLine)
   )
   (if
      PI_CheckList
      (not (vl-some 'not PI_CheckList))
   )
)

(defun _AngleList (AL_Integer / AL_Step AL_Factor AL_Return)
   (setq AL_Step (/ 2.0 AL_Integer))
   (setq AL_Factor 0.0)
   (repeat AL_Integer
      (setq AL_Return (append AL_Return (list (+ 0.0 AL_Factor))))
      (setq AL_Factor (+ AL_Factor AL_Step))
   )
   AL_Return
)

; 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))
   )
)
Message 48 of 82
john.uhden
in reply to: lando7189

@lando7189 wrote, "As far a a list of blocks... you can easily incorporate one of the GUI functions in DOSLib with just a few lines of code."

 

Excellent suggestion.  I was just being lazy.

John F. Uhden

Message 49 of 82
Anonymous
in reply to: DannyNL

Hi DannyNL,

 

I checked your revised routine and it is all working great. Thanks for the help and support.

 

I have a small request though. Is there a way to change the function call from the current BC to BCPL ? Not sure how difficult is this, since I am not very familiar with lisp programming syntax. The reason for this request ( more of a personal in nature) is because I have another lisp loaded in AutoCAD with same function call as BC.lsp ( thanks to Gary Annable for the routine to count specific blocks in a drawing). 

 

As for the additional requests I have made in my previous posts - I have found 2 awesome routines ( CountV1-5.lsp and TCountV1-1.lsp - Credit goes to original programmer Lee-MAC Programming - Thank you Lee). The CountV1-5.lsp counts the selected blocks and return the results in a table format; and the TCountV1-1.lsp  extracts the attribute data from the selected blocks and return the results in a table format.) If some one can incorporate these two lisps in their routines, then I think we have a comprehensive routine which is robust enough.

 

I am attaching the Autocad drawing where I have made those tables using those routines, and an intended Table with block counts and attribute values ( manually combined). I have also attached the Lee-Mac Programming Routines I mentioned above for your review and use. All credits goes to Lee-Mac Prog for those two routines used in the current proposed routine.

 

Hope this helps., and thank you all very much for this great help.

 

Regards,

 

VA

Message 50 of 82
DannyNL
in reply to: Anonymous

Changed BlkCounter to BCPL and added code to create a sorted table.

BTW, did not use the supplied .LSP files as it would take me longer the extract the parts that I need than writing new code Smiley Happy

 

(defun c:BCPL (/ BCPL_Selection BCPL_Entity BCPL_LowerLeft BCPL_UpperRight BCPL_PointList BCPL_Result BCPL_Previous BCPL_Count BCPL_EntityList BCPL_CheckLine BCPL_IntersectPoints BCPL_BoundaryCheck BCPL_BlockName BCPL_BlockList BCPL_TableObject BCPL_SortOrder BCPL_BlockListSorted BCPL_RowCount BCPL_Block)  
   (if
      (and
         (princ "\nSelect boundary: ")
         (setq BCPL_Selection (ssget ":S+." '((-4 . "<OR")(0 . "*POLYLINE")(0 . "CIRCLE")(0 . "ELLIPSE")(0 . "SPLINE")(-4 . "OR>"))))
         (setq BCPL_Object (vlax-ename->vla-object (ssname BCPL_Selection 0)))
         (vlax-Curve-isClosed BCPL_Object)
         (vlax-Curve-isPlanar BCPL_Object)
         (setq BCPL_PointList (_GetBoundingBox BCPL_Object))
         (setq BCPL_Selection (ssget "_CP" BCPL_PointList '((0 . "INSERT"))))         
      )                         
      (progn
         (vla-StartUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
         (acet-ui-progress "Counting" (sslength BCPL_Selection))
         (setq BCPL_Count 0)
         (foreach BCPL_Entity (vl-remove-if '(lambda (BCPL_Item) (listp (cadr BCPL_Item))) (ssnamex BCPL_Selection))
            (acet-ui-progress (setq BCPL_Count (1+ BCPL_Count)))
            (setq BCPL_EntityList (entget (setq BCPL_Entity (cadr BCPL_Entity))))
            (if
               (_PointInside (cdr (assoc 10 BCPL_EntityList)) BCPL_Object)
               (progn
                  (if
                     (not (assoc (setq BCPL_BlockID (list (cdr (assoc 2 BCPL_EntityList)) (_ExtractAttributeTagValue (vlax-ename->vla-object BCPL_Entity) "KEY"))) BCPL_BlockList))
                     (setq BCPL_BlockList (cons  (list BCPL_BlockID 1) BCPL_BlockList))
                     (setq BCPL_BlockList (subst (list BCPL_BlockID (1+ (cadr (assoc BCPL_BlockID BCPL_BlockList)))) (assoc BCPL_BlockID BCPL_BlockList) BCPL_BlockList))
                     )
               )
               (ssdel BCPL_Entity BCPL_Selection)
            )
            (if BCPL_CheckLine (entdel BCPL_CheckLine))
         )
         (acet-ui-progress)
         (princ (strcat "\n ** Total number of blocks found: " (itoa (sslength BCPL_Selection)) "\n"))
         (if
            (and
               BCPL_BlockList
               (not (initget 1))
               (not (vl-catch-all-error-p (setq BCPL_TableObject (vl-catch-all-apply '_CreateTable (list (vlax-3d-point (getpoint "\nInsertionpoint for table: ")) (+ (length BCPL_BlockList) 2) 4 11.25 60.0)))))
            )
            (progn               
               (setq BCPL_SortOrder (list "[A-Z]" "[a-z]" "[a-z][a-z]"))
               (foreach BCPL_Pattern BCPL_SortOrder
                  (setq BCPL_BlockListSorted (append BCPL_BlockListSorted (vl-sort (vl-remove-if-not '(lambda (BCPL_Item)(wcmatch (cadr (car BCPL_Item)) BCPL_Pattern)) BCPL_BlockList) '(lambda (BCPL_Item1 BCPL_Item2) (< (cadr (car BCPL_Item1))(cadr (car BCPL_Item2)))))))
               )
               (vla-SetColumnWidth BCPL_TableObject 2 100.0)
               (vla-SetColumnWidth BCPL_TableObject 3 40.0)
               (vla-SetAlignment   BCPL_TableObject acDataRow acMiddleCenter)
               (vla-SetTextHeight2 BCPL_TableObject 0 0 0 6.0)               
               (vla-SetText        BCPL_TableObject 0 0 "Block Data")
               (vla-SetText        BCPL_TableObject 1 0 "Block Preview")
               (vla-SetText        BCPL_TableObject 1 1 "Attribute Value")
               (vla-SetText        BCPL_TableObject 1 2 "Block Name")
               (vla-SetText        BCPL_TableObject 1 3 "Count")
               (setq BCPL_RowCount 2)
               (foreach BCPL_Item BCPL_BlockListSorted                 
                  (if      
                     (not (vl-catch-all-error-p (setq BCPL_Block (vl-catch-all-apply 'vla-item (list (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))) (nth 0 (nth 0 BCPL_Item)))))))      
                     (vl-catch-all-apply 'vla-SetBlockTableRecordId (list BCPL_TableObject BCPL_RowCount 0 (vla-get-ObjectId BCPL_Block) :vlax-true))
                  )
                  (vla-SetText          BCPL_TableObject BCPL_RowCount 1 (cadr (car BCPL_Item)))
                  (vla-SetCellAlignment BCPL_TableObject BCPL_RowCount 2 acMiddleLeft)
                  (vla-SetText          BCPL_TableObject BCPL_RowCount 2 (car (car BCPL_Item)))
                  (vla-SetText          BCPL_TableObject BCPL_RowCount 3 (itoa (cadr BCPL_Item)))
                  (setq BCPL_RowCount (1+ BCPL_RowCount))
               )

            )
         )
         (vla-EndUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
      )
   )
   (princ)
)

(defun _CreateTable (CT_InsertionPoint CT_Rows CT_Columns CT_RowHeigth CT_ColumnWidth)
   (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace)
   (vl-catch-all-apply 'vla-addTable (list (vlax-get-property (vla-get-ActiveDocument (vlax-get-acad-object)) (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace)) CT_InsertionPoint CT_Rows CT_Columns CT_RowHeigth CT_ColumnWidth))
)

(defun _GetBoundingBox (GBB_Object / GBB_LowerLeft GBB_UpperRight)
   (if
      (vlax-method-applicable-p GBB_Object 'GetBoundingBox)
      (progn
         (vla-GetBoundingBox GBB_Object 'GBB_LowerLeft 'GBB_UpperRight)
         (setq GBB_LowerLeft  (vlax-safearray->list GBB_LowerLeft))
         (setq GBB_UpperRight (vlax-safearray->list GBB_UpperRight))
         (list
            GBB_LowerLeft
            (list (nth 0 GBB_UpperRight) (nth 1 GBB_LowerLeft) 0.0)
            GBB_UpperRight
            (list (nth 0 GBB_LowerLeft) (nth 1 GBB_UpperRight) 0.0)
         )
      )
   )
)

(defun _ExtractAttributeTagValue (EATV_BlockObject EATV_Tag / EATV_Return)
   (if
      (and
         (= (type                  EATV_BlockObject) 'VLA-OBJECT)
         (= (vla-get-ObjectName    EATV_BlockObject) "AcDbBlockReference")
         (= (vla-get-HasAttributes EATV_BlockObject) :vlax-true)
         (= (type EATV_Tag) 'STR)
      )
      (progn
         (foreach EATV_Attribute (vlax-safearray->list (vlax-variant-value (vla-GetAttributes EATV_BlockObject)))
            (if
               (and
                  (not EATV_Return)
                  (= (strcase (vla-get-TagString EATV_Attribute)) (strcase EATV_Tag))
               )
               (setq EATV_Return (vla-get-TextString EATV_Attribute))
            )
         )
      )
   )
   EATV_Return
)
         

(defun _PointInside (PI_Point PI_PolylineObject / PI_RayAngles PI_ClosestPoint PI_AngleList PI_RefAngle PI_AngleList PI_CheckLine PI_IntersectPoints PI_CheckList)
   (setq PI_RayAngles (_AngleList 12))
   (setq PI_ClosestPoint (vlax-curve-GetClosestPointTo PI_PolylineObject PI_Point))
   (setq PI_AngleList (mapcar '(lambda (PI_Factor) (* pi PI_Factor)) PI_RayAngles))
   (if
      (not (equal (rem (setq PI_RefAngle (angle PI_Point PI_ClosestPoint)) (/ pi 2.0)) 0))
      (setq PI_AngleList (append (mapcar '(lambda (PI_Factor) (+ (* pi PI_Factor) PI_RefAngle )) PI_RayAngles) PI_AngleList))
   )
   (foreach PI_Angle PI_AngleList
      (setq PI_CheckLine (entmakex (list '(0 . "RAY") '(100 . "AcDbEntity") '(100 . "AcDbRay") (cons 10 PI_Point) (cons 11 (mapcar '- (polar PI_Point PI_Angle 5.0) PI_Point)))))
      (if         
         (not (vl-catch-all-error-p (setq PI_IntersectPoints (vl-catch-all-apply 'vlax-safearray->list (list (vlax-variant-value (vla-IntersectWith (vlax-ename->vla-object PI_CheckLine) PI_PolylineObject acExtendNone)))))))
         (setq PI_CheckList (cons (length (_GroupByNum PI_IntersectPoints 3)) PI_CheckList))
         (setq PI_CheckList (cons nil PI_CheckList))
      )
      (entdel PI_CheckLine)
   )
   (if
      PI_CheckList
      (not (vl-some 'not PI_CheckList))
   )
)

(defun _AngleList (AL_Integer / AL_Step AL_Factor AL_Return)
   (setq AL_Step (/ 2.0 AL_Integer))
   (setq AL_Factor 0.0)
   (repeat AL_Integer
      (setq AL_Return (append AL_Return (list (+ 0.0 AL_Factor))))
      (setq AL_Factor (+ AL_Factor AL_Step))
   )
   AL_Return
)

; 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))
   )
)
Message 51 of 82
DannyNL
in reply to: DannyNL

BTW, change the following line at the beginning of the code from

 

 (setq BCPL_Selection (ssget ":S+." ........

to

 

 (setq BCPL_Selection (ssget "_:S+." ........

So the selection will also work with other international language versions.

 

(Thanks @cadffm Smiley Happy)

Message 52 of 82
Anonymous
in reply to: DannyNL

Hi DannyNL,

 

This is awesome !!!! I am really excited. Thanks for creating the product exactly I requested. I tested the routine and it is all working great. I always request other users should also test this as my work flow and workflow of others could be different. I will wait  for until tomorrow so that if some one comes with any suggestions.

 

In the mean time, (if it is easy, quick and possible) could you please include 4 block selection options as soon as we initiate this routine:

1. Select all blocks (A)

2. Select a polyline boundary (B)

2. Left drag window selection

4. Right drag window selection

 

This way we can include all block counting options in this ONE Lisp routine.

 

As I assume, we can wait until tomorrow  to "Accept as a Solution" if other users want to check and review this lisp.

 

Thanks for all your hard work.

 

Regards,

 

VA

 

 

Message 53 of 82
john.uhden
in reply to: DannyNL

Be careful there, Danny.  We've been through his before.  I think it was back around 2003, which was probably before Kent's time so it was probably Tony T. jumping in.  I had had the theory that if a ray intersects the boundary an odd number of times, then the origin must be inside the boundary.  But Tony pointed out that the ray might intersect just once at a tangent point while its origin was outside the boundary.  So that's when I came up with the idea of summing all the deflections, ergo "Look ma, no rays!"

 

In reviewing and testing my old code for Aquaman I found that my @bulge function assumes that if the PIQ is within a bulged segment that it would fall within the start and end angles measured from the arc's center.  Not necessarily.  with an extreme bulge (internal angle > 180°), the PIQ might fall not within the arc's sector, but between the chord and the center point.  I don't remember why I thought I needed the @bulge function, but now I am thinking of just sticking to the deflections alone.  That is with the exception of checking to see if the PIQ is actually on the boundary.

 

I'm busy doing something else right now, but I'll let you know.

John F. Uhden

Message 54 of 82
Anonymous
in reply to: john.uhden

Hi John.Uhden,

 

Thanks for the heads up, and feedback from your experience and expertise.

 

I personally did not understand much of the technical concerns what you pointed out, but I am sure this has to be looked into before finalizing on it. Any expert advise from any of the CAD gurus are really appreciated, so that we can point out clearly the limitations of these routines.

 

Regards,

 

VA

Message 55 of 82
john.uhden
in reply to: Anonymous

If I can make my @Anonymous function foolproof, then Danny can plug it into his more robust code and you would have no worries.

John F. Uhden

Message 56 of 82
DannyNL
in reply to: john.uhden

John,

 

You're absolutely right, that's why I'm no longer using just one ray to determine if a point is inside the boundary. This was the reason one of my earlier version was missing some blocks as the ray from the insertion point intersected with an even number of points, while being on the inside of the boundary. This was caused by exactly the possibility you described.

 

But the modified routine doesn't just use one ray but multiple, in this case 12 or 24 depending on angle conditions, in all directions. If the point is inside the boundary all rays should have intersections with the boundary and the number of intersections doesn't really matter.

 

Outside - 24 rays.jpg

 

 

Well, thinking about it......it actually does if all rays intersect an even times with the polyline, because in that case the point is enclosed by a complex polyline but actually outside the boundary. I'll make some new modifications to the routine for the situation below.

 

Outside - 24 rays - Error.jpg

Message 57 of 82


@john.uhden wrote:

Be careful there, Danny.  We've been through his before.  I think it was back around 2003, which was probably before Kent's time so it was probably Tony T. jumping in.  I had had the theory that if a ray intersects the boundary an odd number of times, then the origin must be inside the boundary.  But Tony pointed out that the ray might intersect just once at a tangent point while its origin was outside the boundary.  So that's when I came up with the idea of summing all the deflections, ergo "Look ma, no rays!"

 

@Anonymous reviewing and testing my old code for Aquaman I found that my @bulge function assumes that if the PIQ is within a bulged segment that it would fall within the start and end angles measured from the arc's center.  Not necessarily.  with an extreme bulge (internal angle > 180°), the PIQ might fall not within the arc's sector, but between the chord and the center point.  I don't remember why I thought I needed the @bulge function, but now I am thinking of just sticking to the deflections alone.  That is with the exception of checking to see if the PIQ is actually on the boundary.

 

I'm busy doing something else right now, but I'll let you know.


 

pointinpoly.png

 

 

Is the red point inside the green polygon ?

 

It's not like this problem hasn't been studied to death. There's plenty of research on different algorithms. For LISP-based solutions in AutoCAD, I'll still put my money on the BOUNDARY kludge, because it uses the same underlying ACIS APIs that are the product of many years of work.

 

In ObjectARX, this is a one-liner.

 

 

 

 

Message 58 of 82
DannyNL
in reply to: Anonymous

@Anonymous, see the code below with multiple selection options.

 

By default it will ask to select a boundary and I've expanded the boundary selection to splines, circles & ellipses besides polyline.

During this prompt you can select 'All' or 'User' (right-click menu, click on keyword in commandline, or key in the wanted option).

 

The 'All' option will select all blocks in the drawing (but will only count the ones with a valid value in the KEY attribute).

The 'User' option gives you the standard AutoCAD select functionality to manually select the blocks. By default this will be select on object or window/crossing depending if you move right/left after selecting a point. As this is normal selection behavior you can use all selection options AutoCAD offers, like Fence, CrossingPolygon, etc.. So if you want to force a Window selection independent if you drag left/right, just key in 'W' at the select objects prompt. The selected blocks are also only counted if the KEY attribute has a valid value).

 

This modified code is also more accurate in determining if a block is inside the boundary or not. I've found the previous versions to include the blocks if they were exactly on the edge of the boundary, but with this modified code those blocks are excluded (this can be made optional). Also blocks completely enclosed by a complex polyline (see second image in my previous post) will now be excluded.

 

Another addition is when you need to select a location for your table, the size of the table will now be shown as a preview to make it easier to select a suitable location. However, due to this preview you cannot use the OSNAPS to select an insertion point for your table.

 

(defun c:BCPL (/ *error*              BCPL_Block           BCPL_BLOCKID         BCPL_BlockList       BCPL_BlockListSorted BCPL_BlockName
                 BCPL_BoundaryCheck   BCPL_CheckLine       BCPL_Count           BCPL_Entity          BCPL_EntityList      BCPL_IntersectPoints
                 BCPL_LowerLeft       BCPL_NewLocation     BCPL_OBJECT          BCPL_PointList       BCPL_Previous        BCPL_Result
                 BCPL_RowCount        BCPL_Selection       BCPL_SortOrder       BCPL_TableObject     BCPL_UpperRight      BCPL_UserSelect)
  (defun *error* (BCPL_Message)
     (if
        (and
           (= (type BCPL_TableObject) 'VLA-OBJECT)
           (not (vlax-object-released-p BCPL_TableObject))
         )
         (progn
            (vla-Delete BCPL_TableObject)
            (setq BCPL_TableObject nil)            
         )
     )
     (if (not (wcmatch (strcase BCPL_Message T) "*break,*cancel*,*exit*"))
        (princ (strcat "\nError: " BCPL_Message))
     )
     (princ)   
   )
   (if
      (or
         (and
            (not (initget (+ 1 2 4) "All User"))
            (setq BCPL_UserSelect (entsel "\nSelect polyline boundary [All/User]: "))
            (/= (type BCPL_UserSelect) 'STR)
            (= (type (car BCPL_UserSelect)) 'ENAME)
            (member (vla-get-ObjectName (setq BCPL_Object (vlax-ename->vla-object (car BCPL_UserSelect)))) '("AcDbPolyline" "AcDb2dPolyline" "AcDbCircle" "AcDbEllipse" "AcDbSpline"))
            (vlax-Curve-isClosed BCPL_Object)
            (vlax-Curve-isPlanar BCPL_Object)
            (setq BCPL_PointList (_GetBoundingBox BCPL_Object))
            (setq BCPL_Selection (ssget "_CP" BCPL_PointList '((0 . "INSERT"))))
         )
         (and
            (= BCPL_UserSelect "All")
            (setq BCPL_Selection (ssget "_X" '((0 . "INSERT"))))
         )
         (and
            (= BCPL_UserSelect "User")
            (princ "\nSelect blocks: ")
            (setq BCPL_Selection (ssget '((0 . "INSERT"))))
         )         
      )                         
      (progn
         (vla-StartUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
         (acet-ui-progress "Counting" (sslength BCPL_Selection))
         (setq BCPL_Count 0)
         (foreach BCPL_Entity (vl-remove-if '(lambda (BCPL_Item) (listp (cadr BCPL_Item))) (ssnamex BCPL_Selection))
            (acet-ui-progress (setq BCPL_Count (1+ BCPL_Count)))
            (setq BCPL_EntityList (entget (setq BCPL_Entity (cadr BCPL_Entity))))
            (if
               (or
                  (= BCPL_UserSelect "All")
                  (= BCPL_UserSelect "User")                 
                  (_PointInside (cdr (assoc 10 BCPL_EntityList)) BCPL_Object nil)
               )
               (progn
                  (if
                     (not (assoc (setq BCPL_BlockID (list (cdr (assoc 2 BCPL_EntityList)) (_ExtractAttributeTagValue (vlax-ename->vla-object BCPL_Entity) "KEY"))) BCPL_BlockList))
                     (setq BCPL_BlockList (cons  (list BCPL_BlockID 1) BCPL_BlockList))
                     (setq BCPL_BlockList (subst (list BCPL_BlockID (1+ (cadr (assoc BCPL_BlockID BCPL_BlockList)))) (assoc BCPL_BlockID BCPL_BlockList) BCPL_BlockList))
                  )
               )
               (ssdel BCPL_Entity BCPL_Selection)
            )
            (if BCPL_CheckLine (entdel BCPL_CheckLine))
         )
         (acet-ui-progress)
         (princ (strcat "\n ** Total number of blocks found: " (itoa (sslength BCPL_Selection)) "\n"))
         (if
            (and
               BCPL_BlockList
               (not (initget 1))
               (not (vl-catch-all-error-p (setq BCPL_TableObject (vl-catch-all-apply '_CreateTable (list (vlax-3d-point '(0.0 0.0 0.0)) (+ (length BCPL_BlockList) 2) 4 11.25 60.0)))))
            )
            (progn
               (vla-put-Visible BCPL_TableObject :vlax-false)
               (setq BCPL_SortOrder (list "[A-Z]" "[a-z]" "[a-z][a-z]"))
               (acet-ui-progress "Sorting Blocks" (length BCPL_BlockList))
               (setq BCPL_Count 0)
               (foreach BCPL_Pattern BCPL_SortOrder
                  (acet-ui-progress (setq BCPL_Count (1+ BCPL_Count)))                  
                  (setq BCPL_BlockListSorted (append BCPL_BlockListSorted (vl-sort (vl-remove-if-not '(lambda (BCPL_Item)(wcmatch (cadr (car BCPL_Item)) BCPL_Pattern)) BCPL_BlockList) '(lambda (BCPL_Item1 BCPL_Item2) (< (cadr (car BCPL_Item1))(cadr (car BCPL_Item2)))))))
               )
               (acet-ui-progress)
               (acet-ui-progress "Creating Table" (length BCPL_BlockListSorted))
               (setq BCPL_Count 0)               
               (vla-SetColumnWidth BCPL_TableObject 2 100.0)
               (vla-SetColumnWidth BCPL_TableObject 3 40.0)
               (vla-SetAlignment   BCPL_TableObject acDataRow acMiddleCenter)
               (vla-SetTextHeight2 BCPL_TableObject 0 0 0 6.0)               
               (vla-SetText        BCPL_TableObject 0 0 "Block Data")
               (vla-SetText        BCPL_TableObject 1 0 "Block Preview")
               (vla-SetText        BCPL_TableObject 1 1 "Attribute Value")
               (vla-SetText        BCPL_TableObject 1 2 "Block Name")
               (vla-SetText        BCPL_TableObject 1 3 "Count")
               (setq BCPL_RowCount 2)
               (foreach BCPL_Item BCPL_BlockListSorted
                  (acet-ui-progress (setq BCPL_Count (1+ BCPL_Count)))
                  (if      
                     (not (vl-catch-all-error-p (setq BCPL_Block (vl-catch-all-apply 'vla-item (list (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))) (nth 0 (nth 0 BCPL_Item)))))))      
                     (vl-catch-all-apply 'vla-SetBlockTableRecordId (list BCPL_TableObject BCPL_RowCount 0 (vla-get-ObjectId BCPL_Block) :vlax-true))
                  )
                  (vla-SetText          BCPL_TableObject BCPL_RowCount 1 (cadr (car BCPL_Item)))
                  (vla-SetCellAlignment BCPL_TableObject BCPL_RowCount 2 acMiddleLeft)
                  (vla-SetText          BCPL_TableObject BCPL_RowCount 2 (car (car BCPL_Item)))
                  (vla-SetText          BCPL_TableObject BCPL_RowCount 3 (itoa (cadr BCPL_Item)))
                  (setq BCPL_RowCount (1+ BCPL_RowCount))
               )
               (acet-ui-progress)
               (vla-GetBoundingBox BCPL_TableObject 'BCPL_LowerLeft 'BCPL_UpperRight)
               (princ "\nSpecify table position: ")
               (setq BCPL_NewLocation (_DrawBox (vlax-safearray->list BCPL_LowerLeft) (vlax-safearray->list BCPL_UpperRight)))
               (if
                  (listp BCPL_NewLocation)
                  (progn
                     (vla-Move BCPL_TableObject (vlax-3d-point '(0.0 0.0 0.0)) (vlax-3d-point BCPL_NewLocation))
                     (vla-put-Visible BCPL_TableObject :vlax-true)
                  )
                  (progn
                     (vla-Delete BCPL_TableObject)
                     (princ "\n ** Table creation cancelled by user!")
                  )
               )
               (vlax-release-object BCPL_TableObject)
               (setq BCPL_TableObject nil)
            )
         )
         (vla-EndUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
      )
   )
   (princ)
)

(defun _DrawBox (DB_Point1 DB_Point2 / DB_Distance DB_Width DB_Height DB_UserPoint)
   (setq DB_Distance (mapcar '- DB_Point2 DB_Point1))
   (setq DB_Width    (nth 0 DB_Distance))
   (setq DB_Height   (nth 1 DB_Distance))
   (while
      (= (car (setq DB_UserPoint (grread nil 13 0))) 5)
      (redraw)
      (setq DB_UserPoint (reverse (cdr (reverse (cadr DB_UserPoint))))
            DB_UserPoint (trans DB_UserPoint 1 2)
      )
      (grvecs
         (list
            1
            DB_UserPoint  (list (+ (car DB_UserPoint) DB_Width) (cadr DB_UserPoint))
            (list (+ (car DB_UserPoint) DB_Width) (cadr DB_UserPoint)) (list (+ (car DB_UserPoint) DB_Width) (- (cadr DB_UserPoint) DB_Height))
            (list (+ (car DB_UserPoint) DB_Width) (- (cadr DB_UserPoint) DB_Height)) (list (car DB_UserPoint) (- (cadr DB_UserPoint) DB_Height))
            (list (car DB_UserPoint) (cadr DB_UserPoint)) (list (car DB_UserPoint) (- (cadr DB_UserPoint) DB_Height))
         )         
      )  
   )
   (redraw)
   (cadr DB_UserPoint)
)

(defun _CreateTable (CT_InsertionPoint CT_Rows CT_Columns CT_RowHeigth CT_ColumnWidth)   
   (vl-catch-all-apply 'vla-addTable (list (vlax-get-property (vla-get-ActiveDocument (vlax-get-acad-object)) (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace)) CT_InsertionPoint CT_Rows CT_Columns CT_RowHeigth CT_ColumnWidth))
)

(defun _GetBoundingBox (GBB_Object / GBB_LowerLeft GBB_UpperRight)
   (if
      (vlax-method-applicable-p GBB_Object 'GetBoundingBox)
      (progn
         (vla-GetBoundingBox GBB_Object 'GBB_LowerLeft 'GBB_UpperRight)
         (setq GBB_LowerLeft  (vlax-safearray->list GBB_LowerLeft))
         (setq GBB_UpperRight (vlax-safearray->list GBB_UpperRight))
         (list
            GBB_LowerLeft
            (list (nth 0 GBB_UpperRight) (nth 1 GBB_LowerLeft) 0.0)
            GBB_UpperRight
            (list (nth 0 GBB_LowerLeft) (nth 1 GBB_UpperRight) 0.0)
         )
      )
   )
)

(defun _ExtractAttributeTagValue (EATV_BlockObject EATV_Tag / EATV_Return)
   (if
      (and
         (= (type                  EATV_BlockObject) 'VLA-OBJECT)
         (= (vla-get-ObjectName    EATV_BlockObject) "AcDbBlockReference")
         (= (vla-get-HasAttributes EATV_BlockObject) :vlax-true)
         (= (type EATV_Tag) 'STR)
      )
      (progn
         (foreach EATV_Attribute (vlax-safearray->list (vlax-variant-value (vla-GetAttributes EATV_BlockObject)))
            (if
               (and
                  (not EATV_Return)
                  (= (strcase (vla-get-TagString EATV_Attribute)) (strcase EATV_Tag))
               )
               (setq EATV_Return (vla-get-TextString EATV_Attribute))
            )
         )
      )
   )
   (if
      (not EATV_Return)
      ""
      EATV_Return
   )
)
         
(defun _PointInside (PI_Point PI_PolylineObject PI_OnEdgeTrue / PI_ClosestPoint PI_Distance PI_RayAngles PI_AngleList PI_RefAngle PI_AngleList PI_CheckLine PI_IntersectPoints PI_CheckList PI_Return)   
   (setq PI_ClosestPoint (vlax-curve-GetClosestPointTo PI_PolylineObject PI_Point))
   (setq PI_Distance (distance PI_Point PI_ClosestPoint))
   (if      
      (not (equal PI_Distance 0.0))
      (progn              
         (setq PI_RayAngles (_AngleList 12))
         (setq PI_AngleList (mapcar '(lambda (PI_Factor) (* pi PI_Factor)) PI_RayAngles))
         (if
            (not (equal (rem (setq PI_RefAngle (angle PI_Point PI_ClosestPoint)) (/ pi 2.0)) 0))
            (setq PI_AngleList (append (mapcar '(lambda (PI_Factor) (+ (* pi PI_Factor) PI_RefAngle )) PI_RayAngles) PI_AngleList))
         )
         (foreach PI_Angle PI_AngleList
            (setq PI_CheckLine (entmakex (list '(0 . "RAY") '(100 . "AcDbEntity") '(100 . "AcDbRay") (cons 10 PI_Point) (cons 11 (mapcar '- (polar PI_Point PI_Angle 5.0) PI_Point)))))
            (if         
               (not (vl-catch-all-error-p (setq PI_IntersectPoints (vl-catch-all-apply 'vlax-safearray->list (list (vlax-variant-value (vla-IntersectWith (vlax-ename->vla-object PI_CheckLine) PI_PolylineObject acExtendNone)))))))
               (setq PI_CheckList (cons (length (_GroupByNum PI_IntersectPoints 3)) PI_CheckList))
               (setq PI_CheckList (cons nil PI_CheckList))
            )
            (entdel PI_CheckLine)
         )
      )
   )
   (cond
      (
         (and
            (equal PI_Distance 0.0)
            PI_OnEdgeTrue
         )
         T
      )
      (
         (and
            (not (vl-some 'not PI_CheckList))
            (vl-some '(lambda (PI_Value) (= (rem PI_Value 2) 1)) PI_CheckList)
         )
         T         
      )
      (
         T
         nil
      )
   )               
)

(defun _AngleList (AL_Integer / AL_Step AL_Factor AL_Return)
   (setq AL_Step (/ 2.0 AL_Integer))
   (setq AL_Factor 0.0)
   (repeat AL_Integer
      (setq AL_Return (append AL_Return (list (+ 0.0 AL_Factor))))
      (setq AL_Factor (+ AL_Factor AL_Step))
   )
   AL_Return
)

; 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))
   )
)
Message 59 of 82
Anonymous
in reply to: DannyNL

Hi DannyNL,

 

Thank You so much Danny. I think we have a comprehensive, robust and user friendly routine now. From what all tests I have done so far, every thing is working great. When I say every thing, I am saying about my kind of work flow. I highly suggest other users to try this routine out so that if any improvement needed can be done.

 

Personally I want to thank all the CAD experts out here who put their valuable inputs and contributed with their years of knowledge and experience in improving this product in each stage of its development. I would like to specially mention experts like Kent1Cooper, John.Uhden, BeeKeeCZ, CADffm, ActivistInvester,lando7189, and maratovich in this regard. I would like to also thank Cad Elite users like Lee-Mac Programming,  and any other users whose previous work/ routines has contributed or used by experts who worked on this current routines. All credit goes to those users whose code/ logic/ wisdom has contributed in developing this current code.

 

To sum every thing up:

 

DannyNL's routine which has come up as a final user interactive product. The Name of the routine is BCPL

 

We have got other routines from the following people which is equally good and working, and could be used as routines for further improvement and consideration for different workflows. These could also be used for checking and evaluating other routines of similar nature. Those include:

John.Uhden's - BIB

ActivistInvester's - SELECTCONTAINEDINSERTS

BeeKeeCZ's - BCountIn

 

All four routines are working great in most of my tests/ evaluations in my work flow. Please find attached all the lisps ( 4 routines zipped) and the AutoCAD file to check these routines if other users want to use it/ evaluate/ improve upon it.

 

I am not sure whether I can click Accept as Solution for more than one posts. I really want to Accept these Four Routines as Solutions, but first I am going to Accept DannyNL's routine. If it allows me to do more than one, then I will accept the other three as well.

 

Thank you all once again for making this happen and rendering help to the CAD community.

 

Regards,

 

VA

 

 

Message 60 of 82
john.uhden
in reply to: DannyNL

Very interesting.
I found out that I had added my @bulge function in an attempt to avoid
summing deflections at tight intervals around a bulged segment (too much
time). And I found the reason while it will fail if the bulge is > 1.0.
So now I am wracking my brain to figure out a better way. I have an idea
but it looks rather complex. I don't like imperfections.

John F. Uhden

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report