Jump to content

Recommended Posts

Posted (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 hole.png 

polyline for the holes.dwg

 

DrawPLHoles.png

Edited by Nikon
Posted

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
)

 

  • Thanks 1
Posted
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.

lwpolyline.png

Posted

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?

IMG_20250515_132303.thumb.jpg.9fbf5ab22dce4b4912520d5628d39202.jpg

Posted (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.

diagonal2.png

Edited by Nikon
Posted

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)
)

 

  • Like 1
Posted
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!

Posted

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)
)

 

  • Like 1
Posted
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...

Posted (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.  

 

incorrect.png

 

enlarge the image.png

Edited by Nikon
Posted

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)

 

  • Like 1
Posted (edited)

Another option: disable object snaps

Edited by GLAVCVS
  • Thanks 1
Posted
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.

  • Like 1
Posted (edited)
4 hours ago, GLAVCVS said:

Another option:

disable object snaps

(defun c:alertMg( ) 
(alert "¡Muchas gracias!")
  (princ)
)
(c:alertMg)

 

Edited by Nikon
  • Like 1
Posted
23 minutes ago, Nikon said:
(defun c:alertMg( ) 
(alert "¡Muchas gracias!")
  (princ)
)
(c:alertMb)

 

😄😄

  • Thanks 1

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...