Nikon Posted May 14 Posted May 14 (edited) I want to get a polyline inside the selected rectangles to mark the hole. Approximate algorithm: Determine the lower-left, upper-left, and upper-right corner (or the corresponding points). Calculate the offset (for example, 1/4 from the smaller side of the rectangle). The offset point must be at the same distance from the left and top edges, i.e. diagonally inward from the upper-left corner. To build a polyline: lower left → offset point → upper right. (defun c:DrawPLHoles (/ ss i ent rect-obj coords pts pt1 pt2 pt3 width height minSide offset v1 v2 v_sum v_len pt2_in) (setq ss (ssget '((0 . "LWPOLYLINE")))) (if ss (progn (setq i 0) (repeat (sslength ss) (setq ent (ssname ss i)) (setq rect-obj (vlax-ename->vla-object ent)) (setq coords (vlax-safearray->list (vlax-variant-value (vla-get-Coordinates rect-obj)))) ;; get 4 vertices (setq pts (list (list (nth 0 coords) (nth 1 coords)) (list (nth 2 coords) (nth 3 coords)) (list (nth 4 coords) (nth 5 coords)) (list (nth 6 coords) (nth 7 coords)) )) ;; Sort by X, then by Y (setq pts (vl-sort pts '(lambda (a b) (if (= (car a) (car b)) (< (cadr a) (cadr b)) (< (car a) (car b)) )))) ;; pt1 — lower left, pt2 — upper left, pt3 — upper right (setq pt1 (nth 0 pts)) (setq pt2 (nth 1 pts)) (setq pt3 (nth 2 pts)) ;; Defining the width and height (setq width (distance pt2 pt3)) (setq height (distance pt1 pt2)) (setq minSide (min width height)) ;; Offset, for example, 1/4 from the smaller side (setq offset (/ minSide 4.0)) ;; Vectors: down and right (setq v1 (mapcar '- pt1 pt2)) ; down (setq v2 (mapcar '- pt3 pt2)) ; right ;; Sum of vectors (bisector) (setq v_sum (mapcar '+ v1 v2)) ;; offset (setq v_len (distance '(0 0) v_sum)) (setq v_sum (mapcar '(lambda (x) (* offset (/ x v_len))) v_sum)) (setq pt2_in (mapcar '+ pt2 v_sum)) (command "_.PLINE" pt1 pt2_in pt3 "") (setq i (1+ i)) ) ) ) (princ) ) polyline for the holes.dwg Edited May 14 by Nikon Quote
BIGAL Posted May 15 Posted May 15 Ok you need a couple of defuns then its easy. 1st defun is it clockwise or anticlockwise. Set to CW. 2nd rotate the rectang points till lower left is the 1st point The draw pline then is easy as using a polar with angle pt2 pt4. ; Checking if pline is CW or CCW and set to CCW ; Orignal idea by Kent Cooper, 1 August 2018 Offsetinorout.lsp ; By Alan H July 2020 (defun AH:chkcwccw (ent / objnew area1 area2 obj minpoint maxpoint) (setq obj (vlax-ename->vla-object ent)) (vla-GetBoundingBox obj 'minpoint 'maxpoint) (setq pointmin (vlax-safearray->list minpoint)) (setq pointmax (vlax-safearray->list maxpoint)) (setq dist (/ (distance pointmin pointmax) 20.0)) (vla-offset obj dist) (setq objnew (vlax-ename->vla-object (entlast))) (setq area1 (vlax-get objnew 'Area)) (vla-delete objnew) (vla-offset obj (- dist)) (setq objnew (vlax-ename->vla-object (entlast))) (setq area2 (vlax-get objnew 'Area)) (vla-delete objnew) (if (> area1 area2) (progn ;(command "reverse" ent "") (alert "needs reverse ") (setq y (+ y 1)) ) ) ) (defun rotate-rectang (lst / corner) (setq corner ; find left most corner with a sort (car (vl-sort lst (function (lambda (a b) (if (equal (car a) (car b) 1e-4) (< (cadr a) (cadr b)) (< (car a) (car b)) ) ) ) ) ) ) (while (/= (car lst) corner) ; rotate until corner is the first item (setq lst (append (cdr lst) (list (car lst)))) ) lst ; return lst ) 1 Quote
Nikon Posted May 15 Author Posted May 15 10 hours ago, BIGAL said: Ok you need a couple of defuns then its easy. then its easy. 1st defun is it clockwise or anticlockwise. Set to CW. 2nd rotate the rectang points till lower left is the 1st point The draw pline then is easy as using a polar with angle pt2 pt4. Please forgive my amateurishness... I'm not really sure, but I don't think I need 2 defuns. Why do I need to rotate the rectangles? defun rotate-rectang? I just need to draw a polyline at points 1-2-3, and then offset point 2 down-to the right at 45 degrees by an amount equal to 1/4 of the smaller side of the rectangle. I select several rectangles. Then a two-segment polyline is created in each rectangle. Then the middle vertex of the polyline is offset. Quote
GLAVCVS Posted May 15 Posted May 15 Hi Nikon There's an important detail: Are you sure the length of point 2 has to be shifted by 1/4 of the short side? Wouldn't it be a little more, since it's the hypotenuse of a right triangle? Quote
Nikon Posted May 15 Author Posted May 15 (edited) 56 minutes ago, GLAVCVS said: Are you sure the length of point 2 has to be shifted by 1/4 of the short side? n't it be a little more, since it's the hypotenuse of a right triangle? Hi @GLAVCVS No, it's not related to the hypotenuse. I'm drawing a line from point 2 at a 45 degree angle. The intersection of two lines: a perpendicular to the smaller side at a distance of 1/4 from point 2 and a line at an angle of 45 degrees. Edited May 15 by Nikon Quote
GLAVCVS Posted May 15 Posted May 15 Your code can be as simple as this... (defun c:DrawPLHoles (/ ss i ent rect-obj coords pts pt1 pt2 pt3 width height minSide offset v1 v2 v_sum v_len pt2_in xmin ymin xmax ymax lc pt ) (setq ss (ssget '((0 . "LWPOLYLINE")))) (if ss (progn (setq i 0) (repeat (sslength ss) (setq ent (ssname ss i)) (setq rect-obj (vlax-ename->vla-object ent)) (setq coords (vlax-safearray->list (vlax-variant-value (vla-get-Coordinates rect-obj)) ) ) ;; get 4 vertices (setq pts (list (list (nth 0 coords) (nth 1 coords)) (list (nth 2 coords) (nth 3 coords)) (list (nth 4 coords) (nth 5 coords)) (list (nth 6 coords) (nth 7 coords)) ) xmin (apply 'min (mapcar 'car pts)) ymin (apply 'min (mapcar 'cadr pts)) xmax (apply 'max (mapcar 'car pts)) ymax (apply 'max (mapcar 'cadr pts)) lc (/ (min (- xmax xmin) (- ymax ymin)) 4.0) pt (list (+ xmin lc) (- ymax lc)) ) (command "_PLINE" (list xmin ymin) pt (list xmax ymax) "") (setq i (1+ i)) ) ) ) (princ) ) 1 Quote
Nikon Posted May 15 Author Posted May 15 9 minutes ago, GLAVCVS said: Your code can be as simple as this... (defun c:DrawPLHoles (/ ss i ent rect-obj coords pts pt1 pt2 pt3 width height minSide offset v1 v2 v_sum v_len pt2_in xmin ymin xmax ymax lc pt ) (setq ss (ssget '((0 . "LWPOLYLINE")))) (if ss (progn (setq i 0) (repeat (sslength ss) (setq ent (ssname ss i)) (setq rect-obj (vlax-ename->vla-object ent)) (setq coords (vlax-safearray->list (vlax-variant-value (vla-get-Coordinates rect-obj)) ) ) ;; get 4 vertices (setq pts (list (list (nth 0 coords) (nth 1 coords)) (list (nth 2 coords) (nth 3 coords)) (list (nth 4 coords) (nth 5 coords)) (list (nth 6 coords) (nth 7 coords)) ) xmin (apply 'min (mapcar 'car pts)) ymin (apply 'min (mapcar 'cadr pts)) xmax (apply 'max (mapcar 'car pts)) ymax (apply 'max (mapcar 'cadr pts)) lc (/ (min (- xmax xmin) (- ymax ymin)) 4.0) pt (list (+ xmin lc) (- ymax lc)) ) (command "_PLINE" (list xmin ymin) pt (list xmax ymax) "") (setq i (1+ i)) ) ) ) (princ) ) Yes! It worked great! Huge thanks? Good luck! Quote
GLAVCVS Posted May 15 Posted May 15 Even simpler: (defun c:DrawPLHoles (/ ss i ent rect-obj coords pts pt1 pt2 pt3 width height minSide offset v1 v2 v_sum v_len pt2_in ) (setq ss (ssget '((0 . "LWPOLYLINE")))) (if ss (progn (setq i 0) (repeat (sslength ss) (setq ent (ssname ss i) pts (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (setq lst (entget ent)))) pts (if (member (cdr (assoc 70 lst)) '(1 129)) (append pts (list (car pts))) pts) xmin (apply 'min (mapcar 'car pts)) ymin (apply 'min (mapcar 'cadr pts)) xmax (apply 'max (mapcar 'car pts)) ymax (apply 'max (mapcar 'cadr pts)) lc (/ (min (- xmax xmin) (- ymax ymin)) 4.0) pt (list (+ xmin lc) (- ymax lc)) ) (command "_PLINE" (list xmin ymin) pt (list xmax ymax) "") (setq i (1+ i)) ) ) ) (princ) ) 1 Quote
Nikon Posted May 15 Author Posted May 15 2 hours ago, GLAVCVS said: Even simpler: (defun c:DrawPLHoles (/ ss i ent rect-obj coords pts pt1 pt2 pt3 width height minSide offset v1 v2 v_sum v_len pt2_in ) (setq ss (ssget '((0 . "LWPOLYLINE")))) (if ss (progn (setq i 0) (repeat (sslength ss) (setq ent (ssname ss i) pts (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (setq lst (entget ent)))) pts (if (member (cdr (assoc 70 lst)) '(1 129)) (append pts (list (car pts))) pts) xmin (apply 'min (mapcar 'car pts)) ymin (apply 'min (mapcar 'cadr pts)) xmax (apply 'max (mapcar 'car pts)) ymax (apply 'max (mapcar 'cadr pts)) lc (/ (min (- xmax xmin) (- ymax ymin)) 4.0) pt (list (+ xmin lc) (- ymax lc)) ) (command "_PLINE" (list xmin ymin) pt (list xmax ymax) "") (setq i (1+ i)) ) ) ) (princ) ) The simple, the more brilliant... Quote
Nikon Posted May 16 Author Posted May 16 (edited) I've tasted the code @GLAVCVS a bit in Autocad 2021... Sometimes the code doesn't work correctly, but if you zoom in and call the command again, the code works. Edited May 16 by Nikon Quote
GLAVCVS Posted May 16 Posted May 16 It's probably OSMODE. When the pickbox on the screen is as large as the polyline's movement, if the 'endpoint' object snap is enabled, then (command "_pline" ...) it won't be able to avoid the OSMODE magnet. But if you zoom in, the pickbox will be smaller, and the problem won't occur. So, simply write on the first line of code: (setvar "OSMODE" 0) 1 Quote
GLAVCVS Posted May 16 Posted May 16 (edited) Another option: disable object snaps Edited May 16 by GLAVCVS 1 Quote
Nikon Posted May 16 Author Posted May 16 18 minutes ago, GLAVCVS said: It's probably OSMODE. When the pickbox on the screen is as large as the polyline's movement, if the 'endpoint' object snap is enabled, then (command "_pline" ...) it won't be able to avoid the OSMODE magnet. But if you zoom in, the pickbox will be smaller, and the problem won't occur. So, simply write on the first line of code: (setvar "OSMODE" 0) Thanks, it solved the problem. 1 Quote
Nikon Posted May 16 Author Posted May 16 (edited) 4 hours ago, GLAVCVS said: Another option: disable object snaps (defun c:alertMg( ) (alert "¡Muchas gracias!") (princ) ) (c:alertMg) Edited May 16 by Nikon 1 Quote
GLAVCVS Posted May 16 Posted May 16 23 minutes ago, Nikon said: (defun c:alertMg( ) (alert "¡Muchas gracias!") (princ) ) (c:alertMb) 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.