GLAVCVS Posted March 12 Posted March 12 That's a good question. It's not as easy as it might seem at first glance. Although having a closed polyline makes the job easier. Just one thing should be clear: calculating the polygon's centroid isn't always effective. A more elaborate algorithm is needed. 1 Quote
GLAVCVS Posted March 12 Posted March 12 I will not answer your question for now, because I am interested in knowing the possible solutions proposed by others. 1 Quote
Saxlle Posted March 12 Posted March 12 Hi @maahee, You can first select that object using (setq obj (car (entsel "\nSelect the object:"))) ;an example Then you can read a X, Y values from closed polygon (if it's from polyline) using (setq ptlist (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget obj)))) And at final, you can use (setq pts (ssget "_WP" ptlist '((0 . "POINT"))) I hope you will find a right way to do that. 1 Quote
Saxlle Posted March 12 Posted March 12 (edited) Also, you didn't mentioned what is that point in the polygon, what it present. Can you describe it more or give an example file? Edited March 12 by Saxlle 1 Quote
maahee Posted March 12 Author Posted March 12 On 3/12/2025 at 12:56 PM, Saxlle said: Also, you didn't mentioned what is that point in the polygon, what it present. Can you describe it more or give an example file? Expand I verified the text insertion point inside the polygon, and then it was placed into the middle of the polygon Quote
Saxlle Posted March 12 Posted March 12 So, if from variable pts you get something like "<Selection set: 3121e>", that means the TEXT is inside the polygon, otherwise, you will get nil. Instead of (0 . "POINT") you need to use (0 . "TEXT"). On 3/12/2025 at 1:01 PM, maahee said: then it was placed into the middle of the polygon Expand This part I don't understand. 1 Quote
GLAVCVS Posted March 13 Posted March 13 On 3/12/2025 at 3:11 PM, Lee Mac said: https://www.theswamp.org/index.php?topic=47969.0 Expand This conversation is very interesting. Marko's concept is interesting. But it has two weaknesses: - If "boundary" doesn't work or works poorly (this often happens in complex drawings), the code fails. - If the point is close to the polyline and there are any odd vertices on the polyline, the following may occur in some cases: 1 Quote
GLAVCVS Posted March 13 Posted March 13 On 3/12/2025 at 3:11 PM, Lee Mac said: https://www.theswamp.org/index.php?topic=47969.0 Expand And your approach of using an X-ray is a very good idea. It hadn't occurred to me. But, above all, the exception handling is flawless. Or at least, I haven't found any. My approach also works with intersections, but to the right and left of the reference point: - odd number of intersections to the right and left = interior point - anything else (after my exception handling) = exterior point. The difference between my approach and yours is that I would have used '(ssget "_F"...)' and would have searched for intersections by traversing the entire perimeter. But for this case, your approach is better. I'll try to adapt my idea as best I can so that it's not too worse than yours. Quote
GLAVCVS Posted March 13 Posted March 13 On 3/12/2025 at 12:54 PM, Saxlle said: Hi @maahee, You can first select that object using (setq obj (car (entsel "\nSelect the object:"))) ;an example Then you can read a X, Y values from closed polygon (if it's from polyline) using (setq ptlist (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget obj)))) And at final, you can use (setq pts (ssget "_WP" ptlist '((0 . "POINT"))) I hope you will find a right way to do that. Expand If the inner text touches any segment of the lwpolyline, '(ssget "WP"...)' would not include the text in the selection set. Also, performing recursive 'ssget's could be too slow on large drawings. 1 1 Quote
LanloyLisp Posted March 13 Posted March 13 It seems there is a confusion now with the topic. Point inside a closed polyline and select points inside a closed polyline, which is which? . Either way, for the first one, I can say by experience, Ray-Casting is the best and fastest approach. For the second one, @Saxlle hit it right, just as the OP wanted. 1 Quote
Saxlle Posted March 13 Posted March 13 On 3/13/2025 at 11:23 AM, GLAVCVS said: If the inner text touches any segment of the lwpolyline, '(ssget "WP"...)' would not include the text in the selection set. Expand Yes @GLAVCVS, that is right, I know it. You can change the text height, and it will included in the selection set (if it still don't touching the boundary from polyline), and the second one can be, if you get a nil from the first ssget with _WP, you can make a selection set with _F (if the text touching the boundary from polyline). Anyway, it's on the @maahee to choose the right way to accomplish what he need. 1 Quote
GLAVCVS Posted March 13 Posted March 13 On 3/13/2025 at 11:26 AM, LanloyLisp said: It seems there is a confusion now with the topic. Point inside a closed polyline and select points inside a closed polyline, which is which? . Either way, for the first one, I can say by experience, Ray-Casting is the best and fastest approach. For the second one, @Saxlle hit it right, just as the OP wanted. Expand Thanks for introducing me to Ray-Casting. To my shame , I must say I wasn't aware of such an algorithm. In return, I can say I came to a similar conclusion years ago. But my algorithm works to the right and left of the reference point, for safety's sake. 1 Quote
GLAVCVS Posted March 14 Posted March 14 Hi I was about to give up completely on the idea of finding intersections with 'RAY' objects on a general set. But at the last minute, I discovered something in @Lee Mac's code that changed my mind: it selects the first perimeter that encloses the reference point and discards the rest. rayF-ezgif.com-gif-to-mp4-converter.mp4 1 Quote
GLAVCVS Posted March 14 Posted March 14 (edited) Solving this involves letting the algorithm analyze the rest of the set and implementing a little more code to filter the results. For this reason, I decided to emphasize my initial approach. Forgive me if I'm a bit long-winded in my explanation, but I believe that for those of us who work in the world of cartography, topography and geographic information systems, these resources are of interest. Therefore, I attach below the results of my approach, which are as follows: - Create a selection set, as limited as possible, of closed polylines that will need to be fully analyzed - Analyze all the perimeters and store those that enclose the reference point - Select and return the one with the smallest area The result, given the limited scope of the analysis (closed polylines), has allowed the required code to be considerably less than expected. Below is the code: ;*************************************** ;****** G L A V C V S F E C I T ****** (defun selR (p / r s l lt en ex d cj i n o r4 f) (defun r4 (p e / r is f) (foreach l '(1.5708 3.141592 4.71239) (setq r (vla-addline i (vlax-3d-point p) (vlax-3d-point (polar p l d)))) (if (setq is (safearray-value (variant-value (vla-intersectWith r e acextendnone)))) (setq f (cons (= (rem (length is) 2) 1) f)) ) (vla-delete r) ) f ) (setq en (getvar "extmin") ex (getvar "extmax") n -1 d (max (- (car ex) (car en)) (- (cadr ex) (cadr en))) ) (if (setq cj (ssget"_X" (list '(0 . "LWP*") '(-4 . "&=") '(70 . 1) (cons 410 (if (= 1 (getvar 'cvport)) (getvar 'ctab) "Model")) '(-4 . "<and") '(-4 . ">,>,*") (list 10 (car p) (- (cadr p) 50.0) 0.0) '(-4 . ">,<,*") (list 10 (car p) (+ (cadr p) 50.0) 0.0) '(-4 . "and>") ) ) ) (while (setq e (ssname cj (setq n (1+ n)))) (setq lt nil) (if (not r) (setq r (vla-addline (setq i (vlax-ename->vla-object (cdr (assoc 330 (entget e))))) (vlax-3d-point p) (vlax-3d-point (polar p 0 d)))) ) (if (setq l (safearray-value (variant-value (vla-intersectWith r (setq o (vlax-ename->vla-object e)) acextendnone)))) (if (= (rem (length (setq l (while l (setq lt (cons (list (nth 0 l) (nth 1 l) (nth 2 l)) lt) l (cdddr l) lt lt)))) 2) 1) (if (and (car (setq f (r4 p o))) (cadr f) (caddr f)) (setq s (if s (if (< (vla-get-area o) (vla-get-area s)) o) o)) ) ) ) ) ) (if r (vla-delete r)) (if s (sssetfirst nil (ssadd (vlax-vla-object->ename s)))) s ) Edited March 14 by GLAVCVS 1 Quote
GLAVCVS Posted March 14 Posted March 14 The function requires the insertion point of the object to be checked as an argument and returns the object name 'vla' of the perimeter polyline. In my opinion, the function is practically bulletproof. But any criticism or suggestions are welcome. I hope it's helpful. Quote
GLAVCVS Posted March 14 Posted March 14 (edited) @maahee Ray-Casting trauma has hit me I forgot your interest was the opposite: checking the point from the lwpolyline I'll fix that right now. ;*************************************** ;****** G L A V C V S F E C I T ****** ; ARGUMENTS: ; lw -> LWPOLYLINE entity name ; p -> can be: -list point ; -TEXT, MTEXT, SHAPE, POINT or INSERT entity name ; -text string (string for make a text selection set by string filter) ; ; Return: list with object/s or list point inside the polyline; or nil (defun inside? (lw p / en ex d r rs l i n o r4 cj) (defun r4 (p e / r is f l) (foreach l '(0 1.5708 3.141592 4.71239) (if (not f) (progn (setq r (vla-addline i (vlax-3d-point p) (vlax-3d-point (polar p l d)))) (if (setq is (safearray-value (variant-value (vla-intersectWith r e 0)))) (setq f (= (rem (length is) 2) 0)) (setq f T) ) (vla-delete r) ) ) ) (not f) ) (setq en (getvar "extmin") ex (getvar "extmax") d (max (- (car ex) (car en)) (- (cadr ex) (cadr en))) i (vlax-ename->vla-object (cdr (assoc 330 (entget lw)))) ) (cond ((= (type p) 'LIST) (if (r4 p (vlax-ename->vla-object lw)) (list p) ) ) ((= (type p) 'ENAME) (if (wcmatch (cdr (assoc 0 (setq l (entget p)))) "*TEXT,SHAPE,POINT,INSERT") (if (r4 (cdr (assoc 10 l)) (vlax-ename->vla-object lw)) (list p) ) ) ) ((= (type p) 'STR) (if (setq cj (ssget "x" (list '(0 . "TEXT") (cons 1 p)))) (if (setq cj (vl-remove-if 'listp (mapcar 'cadr (ssnamex cj)))) (foreach o cj (if (r4 (cdr (assoc 10 (entget o))) (vlax-ename->vla-object lw)) (setq rs (cons o rs)) ) ) ) ) rs ) ) ) Edited Thursday at 10:35 PM by GLAVCVS 1 Quote
GLAVCVS Posted March 14 Posted March 14 This function is multipurpose. You need to accompany it with two arguments: 'lw' is the entity name of the polyline you want to check 'p' can be: a list of points; the entity name of a "TEXT", "MTEXT", "POINT", "SHAPE", or "INSERT" that you want to check if it's within the polyline; or a text string, in which case it will be used as a filter to create a selection set of texts containing that string, and all of which will be checked if they are included in the lwpolyline. In all cases, the function returns, depending on what was entered as the second argument, a list with the point and/or the objects included in the lwpolyline, or nil if none exist. 1 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.