Freerefill Posted July 8, 2009 Posted July 8, 2009 Having now 3.5 AutoLISP games under my belt, I figure it was about time I did something a little more useful than determining if a point was within a circle or an orthographic (is that the right word?) rectangle. It took some doing, but I finally figured it out.. well, almost. There's always an "almost". Now, like so many things I do, I doubt this will be helpful to anyone, but I thought it was a slick solution to a potential problem so I'm posting it. Say you wanted to determine if a point was within any regular or semi-irregular polygon. Well it's hard to do, yeah? There's probably a lot of math involved, and whilst a circle is easy (radius) as is a rectangle (upper and lower axial bounds), there's so much more that should be considered, so many more shapes that we want to see if a point is within or not! And by "we" I mean "me" So I wrote this up. This will do just that: determine if a point is within any regular (id est, all sides and internal angles being equal to one another.. like using the "polygon" command) or semi-irregular (stretched and skewed a bit, but the area of the bounding box of the polygon must equal the area of the polygon itself) polygons. I even did you one further and wrote a function to get the 3D vertices of a polyline and return them as a usable list. Here's the code, short and sweet: (defun inPol(point listy / polLst dum1 ret ang1 ang2); (setq polLst (append listy (list (car listy))) dum1 1 ret nil) (while (< dum1 (length listy)) (setq ang1 (angle (nth dum1 polLst) (nth (1- dum1) polLst)) ang2 (angle (nth dum1 polLst) (nth (1+ dum1) polLst))) (setq ret (cons (not (xor (<= (abs (- ang1 ang2)) pi) (bween (angle (nth dum1 polLst) point) ang1 ang2))) ret)) (setq dum1 (1+ dum1)) ) (not (member nil ret)) ); Test to see if a point is within a given set of vertices defining a polygon (defun xor(inA inB / ); (not (and (not (and inA (not (and inA inB)))) (not (and inB (not (and inA inB)))))) ); Exclusive OR (defun bween(in1 chk1 chk2 / ); (and (numberp in1) (numberp chk1) (numberp chk2) (or (and (> in1 chk1) (< in1 chk2)) (and (< in1 chk1) (> in1 chk2)))) ); Checks to see if in1 is a number between chk1 and chk2 (defun plverts(ent / ret listy retDum add1 add2); (if (= (cdr (assoc 0 (entget (car ent)))) "LWPOLYLINE") (progn (setq ret nil listy (vlax-safearray->list (vlax-variant-value (vla-get-coordinates (vlax-ename->vla-object (car ent)))))) (setq retDum 0) (while (and (setq add1 (nth retDum listy)) (setq add2 (nth (1+ retDum) listy)) (setq ret (append ret (list (list add1 add2 0)))) (setq retDum (+ 2 retDum)))))) ret ); Returns a list of 3D coordinates defining the vertices of a polygon And to give you an idea of what I mean by "regular and semi-irregular", here's a convenient image. And, sorry about attaching the file.. I can't access my Photobucket at the moment. I'll clean it up later. Quote
Freerefill Posted July 8, 2009 Author Posted July 8, 2009 Also, how you create the polygon is important. You can't, say, have 2 vertices overlapping (not that you ever should, but still). I'm sure there are some other things that would screw it up. Basically, the input for the inPol function should have a form similar to: (list (list 0 0 0) (list 1 0 0) (list 0 1 0)) which, you'll note, are simply the three vertices of an isosceles triangle. You'll note that there's nothing funny in there, no extra vertices that are the same and whatnot. I'm sure there's a way to write a check into the function, but it's not meant to determine if a point is within an area bounded by an AutoCAD polyline, it's made to determine if a point is within a polygon defined by the inputted vertices. Quote
Lee Mac Posted July 8, 2009 Posted July 8, 2009 I wrote this a while back, sort of similar: ;; ============ Insidep.lsp =============== ;; ;; MAIN FUNCTION DESCRIPTION: ;; Will determine whether a point lies ;; inside or outside an object. ;; ;; FUNCTION: insidep ;; ARGUMENTS: ;; Point to be tested. ;; Object Ename or VLA-Object ;; ;; FUNCTION: vlax-list->3D-point ;; ARGUMENTS: ;; List to be converted. ;; Flag to determine x or y. ;; ;; OBJECT COMPATIBILITY: ;; Everything except Viewport/Polygon Mesh. ;; ;; AUTHOR: ;; Copyright (c) 2009, Lee McDonnell ;; (Contact Lee Mac, CADTutor.net) ;; ;; PLATFORMS: ;; No Restrictions, ;; only tested in ACAD 2004. ;; ;; ======================================== (defun insidep (pt Obj / Obj Tol ang doc spc flag int lin xV yV) (vl-load-com) (or (eq 'VLA-OBJECT (type Obj)) (setq Obj (vlax-ename->vla-object Obj))) (setq Tol (/ pi 6) ; Uncertainty ang 0.0 flag T) (setq doc (vla-get-ActiveDocument (vlax-get-Acad-Object)) spc (if (zerop (vla-get-activespace doc)) (if (= (vla-get-mspace doc) :vlax-true) (vla-get-modelspace doc) (vla-get-paperspace doc)) (vla-get-modelspace doc))) (while (and (< ang (* 2 pi)) flag) (setq flag (and (setq int (vlax-invoke (setq lin (vla-addLine spc (vlax-3D-point pt) (vlax-3D-point (polar pt ang (if (vlax-property-available-p Obj 'length) (vla-get-length Obj) 1.0))))) 'IntersectWith Obj acExtendThisEntity)) (<= 6 (length int)) (setq xV (vl-sort (vlax-list->3D-point int T) '<) yV (vl-sort (vlax-list->3D-point int nil) '<)) (or (<= (car xV) (car pt) (last xV)) (<= (car yV) (cadr pt) (last yV)))) ang (+ ang Tol)) (vla-delete lin)) flag) (defun vlax-list->3D-point (lst flag) (if lst (cons ((if flag car cadr) lst) (vlax-list->3D-point (cdddr lst) flag)))) ;; Test Function (defun c:test (/ pt ss) (sssetfirst nil nil) (if (and (setq pt (getpoint "\nSelect Point Within Boundary: ")) (setq ss (ssget "X" (list (cons 0 "~VIEWPORT") (if (getvar "CTAB") (cons 410 (getvar "CTAB")) (cons 67 (- 1 (getvar "TILEMODE")))))))) (progn (princ "\nSelecting Everything Visible...\nAnalyzing Surrounding Region...") (foreach ent (mapcar 'cadr (ssnamex ss)) (if (not (insidep pt ent)) (ssdel ent ss))) (if (not (zerop (sslength ss))) (sssetfirst nil ss) (princ "\nPoint Does not lie Within Boundary!"))) (princ "\n<!> No Point Selected or No Objects in Drawing <!>")) (princ)) Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.