gsc Posted November 11, 2020 Share Posted November 11, 2020 Hi, In a lisp routine want to check 3 Cases with a (sub)function if : One of the black Circles is crossing of the red closed Polylines (already found an intersect solution) One of the Circles is fully inside closed red Polylines One of the red closed Polylines are fully inside of one of the black Circles. The 4 black circles are itterated (different locations and headings) to many positions in the field. Keep in mind the red polylines are a clipped example, this can be a whole field of closed polygons Does anyone has an example how to check (by itteration) if a Circle is fully inside one of the red polygons or the other way around? The only goal of the function(s) is that the result of the 4 black circles itteration is TRUE or NIL Greetzzz! Quote Link to comment Share on other sites More sharing options...
Tharwat Posted November 11, 2020 Share Posted November 11, 2020 The following functions are your fiends in this case: 1- vla-intersectwith 2- ssget "_WP" Quote Link to comment Share on other sites More sharing options...
gsc Posted November 11, 2020 Author Share Posted November 11, 2020 17 minutes ago, Tharwat said: The following functions are your fiends in this case: 1- vla-intersectwith 2- ssget "_WP" Hi, To test vla-intersectwith and all the ExtendOption parameters, i found this page: https://www.afralisp.net/archive/methods/lista/intersectwith_method.htm I have created a small test lisp: (defun c:test () (vl-load-com) (setq util (vla-get-utility (vla-get-activedocument (vlax-get-acad-object)))) (vla-getentity util 'obj1 'ip "\nSelect First Object: ") (vla-getentity util 'obj2 'ip "\nSelect Second Object: ") (setq int1 (vla-IntersectWith obj1 obj2 acExtendNone)) (setq int2 (vla-IntersectWith obj1 obj2 acExtendThisEntity)) (setq int3 (vla-IntersectWith obj1 obj2 acExtendOtherEntity)) (setq int4 (vla-IntersectWith obj1 obj2 acExtendBoth)) (princ int1) (princ int2) (princ int3) (princ int4) (princ) ) As a test I have drawn a CIRCLE and a closed LWPOLYLINE But for all 3 Cases I have described in my first post, the result is a Variant (array of doubles): #<variant 8197 ...> #<variant 8197 ...> #<variant 8197 ...> #<variant 8197 ...> I have 2 questions: How can I get the values out of the variant object? Does this also work for Case 2 and 3, where no intersection is between the objects?? Quote Link to comment Share on other sites More sharing options...
Tharwat Posted November 11, 2020 Share Posted November 11, 2020 Use the following method instead then there is no need to convert variants. Where obj1 & obj2 are vla-objects : (vlax-invoke obj1 'intersectwith obj2 AcExtendNone) Quote Link to comment Share on other sites More sharing options...
dlanorh Posted November 11, 2020 Share Posted November 11, 2020 3 hours ago, gsc said: Hi, To test vla-intersectwith and all the ExtendOption parameters, i found this page: https://www.afralisp.net/archive/methods/lista/intersectwith_method.htm I have created a small test lisp: (defun c:test () (vl-load-com) (setq util (vla-get-utility (vla-get-activedocument (vlax-get-acad-object)))) (vla-getentity util 'obj1 'ip "\nSelect First Object: ") (vla-getentity util 'obj2 'ip "\nSelect Second Object: ") (setq int1 (vla-IntersectWith obj1 obj2 acExtendNone)) (setq int2 (vla-IntersectWith obj1 obj2 acExtendThisEntity)) (setq int3 (vla-IntersectWith obj1 obj2 acExtendOtherEntity)) (setq int4 (vla-IntersectWith obj1 obj2 acExtendBoth)) (princ int1) (princ int2) (princ int3) (princ int4) (princ) ) As a test I have drawn a CIRCLE and a closed LWPOLYLINE But for all 3 Cases I have described in my first post, the result is a Variant (array of doubles): #<variant 8197 ...> #<variant 8197 ...> #<variant 8197 ...> #<variant 8197 ...> I have 2 questions: How can I get the values out of the variant object? Does this also work for Case 2 and 3, where no intersection is between the objects?? Use the snippet from @Tharwat above and put it into an if statement and test if there is a return or not. If there is an intersection it will return a list. If not then nil is returned so either test for nil (not) or test length of returned list (if (not (vlax-invoke obj1 'intersectwith obj2 acextendnone)) (doesn't intersect) (intersects) );end_if This should result in a list or nil being returned Quote Link to comment Share on other sites More sharing options...
gsc Posted November 11, 2020 Author Share Posted November 11, 2020 Thanx, I will try as soon as possible. Is this also working for Case 2 and Case 3? (when objects don't intersect but are fully inside) Quote Link to comment Share on other sites More sharing options...
dlanorh Posted November 11, 2020 Share Posted November 11, 2020 Partly, it will only tell you if one intersects the other. In cases 2 and 3 (completely inside or outside) you would need to do additional checks using a raycasting method (not 100% effective) or a winding method. 2. check, is the center of the circle inside the polyline. If there is no intersection and the center of the circle is inside then the whole circle is inside 3. Is the distance from every vertex of the polyline to the center of the circle less than the radius, then if there is no intersection, the polyline is completely inside the circle. Quote Link to comment Share on other sites More sharing options...
gsc Posted November 11, 2020 Author Share Posted November 11, 2020 the 2nd option I do the same The 3rd, (most of them are small polylines in a cluster)...I list the points of all closed polylines, each list is a polyline, then I do the same method as the 2nd, check if all points of one list are inside a Circle...itterative I do the rest of the lists Quote Link to comment Share on other sites More sharing options...
BIGAL Posted November 13, 2020 Share Posted November 13, 2020 For 3 within a circle as already stated you struggle to us ssget as circle is not directly supported as a polygon to search within, you can make a polygon with lots of sides get the the co-ordinates and use that with "WP". It can be an advantage to make the polygon a fraction bigger than the circel. Quote Link to comment Share on other sites More sharing options...
gsc Posted November 13, 2020 Author Share Posted November 13, 2020 (edited) I had in mind to make a squared selection window around each circle and add all found objects to the selection set. A square around the Circle is narrow enough. Another idea is, since the selection set will be quit small (average radius of the circles is 4 to 10 m), to create a merged REGION of Circles and a merged REGION of the Selection Set in a temporary layer, perform an INTERSECT command....if there is an Intersect, there is a resulting REGION shape, if not both REGIONS disappear i.o.w. Layer is empty or not, this would replace all 3 cases described. The advantage would also be that you can create REGIONS with holes How should I approach that? (defun ssExclusionSS ( lyr lst rad / pt1 pt2 ss1 ss2 ent ) ; lyr is layer with possible closed polylines, circles or ellipses ; lst are 4 circle center coordinats ; rad is radius of circles (setq ss1 (ssadd)) (foreach itm lst (setq num 0) ;Set search window boundary (setq pt1 (polar itm (DTR 225) rad)) (setq pt2 (polar itm (DTR 45) rad)) ;Get objects within search window (setq ss2 (ssget "_WP" (list (car pt1) (cadr pt1)) (list (car pt2) (cadr pt2)) (list (cons 8 lyr)))) (if ss2 (progn (repeat (sslength ss2) (setq ent (ssname ss2 num)) (cond ((= (cdr (assoc 0 (entget ent))) "LWPOLYLINE") (ssadd ent ss1) ) ((= (cdr (assoc 0 (entget ent))) "CIRCLE") (ssadd ent ss1) ) ((= (cdr (assoc 0 (entget ent))) "ELLIPSE") (ssadd ent ss1) ) ) ) ) ) (setq num (1+ num)) ) ss1 ) Edited November 13, 2020 by gsc Quote Link to comment Share on other sites More sharing options...
BIGAL Posted November 16, 2020 Share Posted November 16, 2020 Using polygon is easy as with a circle you have a center point and a radius, please note Bricscad uses a different method. pt centre of circle rad is obvius radius (command "polygon" 10 pt "I" rad) ; make a polygon 10 sides (setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (entlast))))) (command "erase" (entlast) "") ; polygon not needed (setq ss (ssget "wP" co-ord )) Quote Link to comment Share on other sites More sharing options...
gsc Posted November 16, 2020 Author Share Posted November 16, 2020 3 hours ago, BIGAL said: Using polygon is easy as with a circle you have a center point and a radius, please note Bricscad uses a different method. pt centre of circle rad is obvius radius (command "polygon" 10 pt "I" rad) ; make a polygon 10 sides (setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (entlast))))) (command "erase" (entlast) "") ; polygon not needed (setq ss (ssget "wP" co-ord )) That is a good option! How about the following approach?: I already have a function (ssExclusionSS) which creates a (narrowed down) selection set of a squared window of objects inside the 4 Circles: (defun ssExclusionSS ( lyr lst rad / pt1 pt2 ss1 ss2 ent ) ; lyr is layer with closed polylines ; lst are 4 circles coordinates ; rad is radius of circles (setq ss1 (ssadd)) (foreach itm lst ;Set search window boundary (setq pt1 (polar itm (DTR 225) (sqrt (+ (* rad rad) (* rad rad))))) (setq pt2 (polar itm (DTR 45) (sqrt (+ (* rad rad) (* rad rad))))) ;Get objects within search window (setq ss2 (ssget "_W" (list (car pt1) (cadr pt1)) (list (car pt2) (cadr pt2)) (list (cons 8 lyr)))) ;Add all found objects to ss1 (if ss2 (progn (setq num 0) (repeat (sslength ss2) (setq ent (ssname ss2 num)) (cond ((= (cdr (assoc 0 (entget ent))) "LWPOLYLINE") (ssadd ent ss1) ) ((= (cdr (assoc 0 (entget ent))) "CIRCLE") (ssadd ent ss1) ) ((= (cdr (assoc 0 (entget ent))) "ELLIPSE") (ssadd ent ss1) ) ) (setq num (1+ num)) ) ) ) ) ss1 ) The returned selection set, selected with above subroutine (ssExclusionSS) may still have objects outside the circle because it searches with a squared window around a circle. The (inCircles) function below must return whether this object is inside or outside the Circle. But instead of one object (obj), as the example shows, I want to feed it with the selection set which is returned with the above subroutine (ssExclusionSS), and itterate the objects: If one (or more) objects are inside Circle then it must return T If all objects are outside the circle then return must be NIL (defun inCircles (obj CirObj / Mi Ma cen rad) (mapcar (function set) '(obj CirObj) (mapcar (function (lambda (x) (if (eq 'VLA-OBJECT (type x)) x (vlax-ename->vla-object x) ) ) ) (list obj CirObj) ) ) (vla-getBoundingBox obj 'Mi 'Ma) (mapcar (function set) '(Mi Ma) (mapcar (function vlax-safearray->list) (list Mi Ma))) (setq cen (vlax-get CirObj 'Center) rad (vla-get-Radius CirObj)) (and (<= (distance Mi cen) rad) (<= (distance Ma cen) rad) (<= (distance (list (car Mi) (cadr Ma)) cen) rad) (<= (distance (list (car Ma) (cadr Mi)) cen) rad) ) ) I got a bit stuck with the subroutine (ssExclusionSS) The AND returns T or NIL for one object, how do I itterate the rest of the objects and still have T or NIL as return? The requirement is: If one (or more) objects are inside the Circle then it must return T If ALL objects are outside the circle then it must return NIL How do I program this? Quote Link to comment Share on other sites More sharing options...
Jonathan Handojo Posted November 16, 2020 Share Posted November 16, 2020 (edited) Poor you. Here, I'll guide you a bit. ;; In all functions, obj and circ are VLA Objects (defun Circle:Case1 (obj circ) (and (vlax-invoke obj 'IntersectWith circ acExtendNone)) ) (defun Circle:Case2 (obj circ / cen ry int) (setq cen (vlax-get circ 'Center) ry (entmakex (list '(0 . "RAY") '(100 . "AcDbEntity") '(100 . "AcDbRay") (cons 10 cen) '(11 1.0 0.0 0.0) ) ) int (vlax-invoke obj 'IntersectWith (vlax-ename->vla-object ry) acExtendNone) ) (entdel ry) (and (not (vlax-invoke obj 'IntersectWith circ acExtendNone)) (= (rem (length int) 6) 3) ) ) (defun Circle:Case3 (obj circ / cen rd) (setq cen (vlax-get circ 'Center) rd (vlax-get circ 'Radius) ) (and (not (vlax-invoke obj 'IntersectWith circ acExtendNone)) (vl-every '(lambda (x) (<= (distance (cdr x) cen) rd)) (vl-remove-if-not '(lambda (a) (= (car a) 10) ) (entget (vlax-vla-object->ename obj)) ) ) ) ) So where all objects within a selection set is outside the circle, it will return nil. Where at least one is inside, it returns T: (defun OneInside (ss circ / i lst) (repeat (setq i (sslength ss)) (setq lst (cons (vlax-ename->vla-object (ssname ss (setq i (1- i)))) lst)) ) (vl-some '(lambda (x) (Circle:Case2 x circ)) lst) ) Edited November 16, 2020 by Jonathan Handojo Quote Link to comment Share on other sites More sharing options...
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.