Jump to content

Perpendicular Lines from many points to a Polyline


rifad_cad

Recommended Posts

Hi, I'm a newbie to autocad LISP and also to the forum. I have to create perpendicular lines to a polyline from points adjoining to it. I can manually do that one by one but I have several thousand points either side of the very long polyline and it is difficult to do that one by one. Is there anyway i can quickly draw perpendicular lines from the points to the polyline. the drawing is 2D and below is a small sample to of the drawing just to illustrate.

 

perpendicular.jpg

Link to comment
Share on other sites

My code used to do a similar thing (you can find it in the list of my replies on this forum): move blocks perperdicular to multiple polylines, first find the closest polyline to the block.

 

I changed it to select points, and to draw lines instead of moving the blocks.  I think it does what you require,

but it has remnants of the old code, so it has lines of code that are not needed anymore.

 

So if you select multiple polylines it will draw a line to the closest one.

 

- Command STO (feel free to change this)

- select polyline(s)

-select points

 



(defun Line (p1 p2)
 (entmakex (list (cons 0 "LINE")
                 (cons 10 p1)
                 (cons 11 p2)
                 )))

;;; Modified code from: http://www.arch-pub.com/Move-point-perpendicular-to-line_10272335.html
;;; By: Mel Franks

(defun c:sto ( / en obj pts_ss ss_len c pten ptobj pted pt pt2 this_is_the_point best_distance)
  (princ "\nSelect polyline: ")
  (setq en (ssget (list
      (cons 0 "ARC,CIRCLE,ELLIPSE,LINE,LWPOLYLINE,POLYLINE,SPLINE")
    ))
  )
  (princ "\nSelect Points: ")
  (setq pts_ss (ssget (list (cons 0 "POINT"))))  
  (setq ss_len (sslength pts_ss))
  (setq c 0)
  (while (< c ss_len)
    (setq pten (ssname pts_ss c))
    (setq ptobj (vlax-ename->vla-object pten))
    (setq pted (entget pten))
    (setq pt (cdr (assoc 10 pted)))

    (setq cnt 0)
    (setq best_distance 1000000)  ;; and we will search for something better.  As long as it keeps dropping we are happy
    (setq this_is_the_point nil)
    (while (< cnt (sslength en))
      (setq ename (ssname en cnt))
      (setq pt2 (vlax-curve-getClosestPointTo ename pt))
      (if (< (distance pt pt2) best_distance) (progn
        (setq best_distance (distance pt pt2))
        (setq this_is_the_point pt2)
      ))
      (setq cnt (+ cnt 1))
    )
    ;;(vla-move ptobj (vlax-3d-point pt) (vlax-3d-point this_is_the_point))
    (Line pt this_is_the_point)
    ;;(vla-Rotate ptobj (vlax-3d-point this_is_the_point) (angle pt this_is_the_point))
    ;;(vla-Rotate ptobj this_is_the_point 1 )
    (setq c (+ c 1))
  )
(princ)
)

  • Thanks 1
Link to comment
Share on other sites

Dear Emmanuel Delay, Thank you very much. The code work very well and it does what I want. 

Just one thing to ask, the text display on the command line always says "Select Object" in both instances (i.e. ask to select 'polyline' and 'points'). see below images. Is it possible to change to 'Select polyline' and 'Select Point'?

Thanks again. 👍

 

1.JPG.98c222ca4e81c3fc055241a90e1c3be1.JPG2.JPG.b0e6e66c2a707c4c8e34ceb982550b58.JPG

Link to comment
Share on other sites

Yes, for example like this:

 


...

  (setvar "nomutt" 1)  ;; shut up ssget
  (setq en (ssget (list
      (cons 0 "ARC,CIRCLE,ELLIPSE,LINE,LWPOLYLINE,POLYLINE,SPLINE")
    ))
  )
  (princ "\nSelect Points: ")
 
  (setq pts_ss (ssget (list (cons 0 "POINT"))))  
  (setq ss_len (sslength pts_ss))
  (setvar "nomutt" 0)  ;; set the variable back

...

  • Thanks 1
Link to comment
Share on other sites

Here's another -

(defun c:ppl ( / ent idx pnt sel )
    (if
        (and (setq sel (LM:ssget "\nSelect points: " '(((0 . "POINT")))))
            (progn
                (while
                    (progn (setvar 'errno 0) (setq ent (entsel "\nSelect curve: "))
                        (cond
                            (   (= 7 (getvar 'errno))
                                (princ "\nMissed, try again.")
                            )
                            (   (null ent) nil)
                            (   (vl-catch-all-error-p (vl-catch-all-apply 'vlax-curve-getclosestpointto ent))
                                (princ "\nInvalid object selected.")
                            )
                        )
                    )
                )
                (setq ent (car ent))
            )
        )
        (repeat (setq idx (sslength sel))
            (setq idx (1- idx)
                  pnt (assoc 10 (entget (ssname sel idx)))
            )
            (entmake (list '(0 . "LINE") pnt (cons 11 (vlax-curve-getclosestpointto ent (cdr pnt)))))
        )
    )
    (princ)
)

;; ssget  -  Lee Mac
;; A wrapper for the ssget function to permit the use of a custom selection prompt
;; msg - [str] selection prompt
;; arg - [lst] list of ssget arguments

(defun LM:ssget ( msg arg / sel )
    (princ msg)
    (setvar 'nomutt 1)
    (setq sel (vl-catch-all-apply 'ssget arg))
    (setvar 'nomutt 0)
    (if (not (vl-catch-all-error-p sel)) sel)
)
(vl-load-com) (princ)

 

Edited by Lee Mac
  • Like 2
Link to comment
Share on other sites

Another one for fun :)

image.png.10436b34d6b973678c6adf155ba76cbf.png

(defun c:foo (/ _dxf _sl a b c e p s x)
  ;; RJP » 2019-01-10
  (defun _sl (s) (cond ((= 'pickset (type s)) (vl-remove-if 'listp (mapcar 'cadr (ssnamex s))))))
  (defun _dxf (c e) (cdr (assoc c (entget e))))
  (cond
    ((setq s (_sl (ssget)))
     (foreach x	s
       (if (wcmatch (_dxf 0 x) "CIRCLE,INSERT,POINT")
	 (setq b (cons (_dxf 10 x) b))
	 (and (= 'real (type (vl-catch-all-apply 'vlax-curve-getendparam (list x))))
	      (setq a (cons x a))
	 )
       )
     )
     (and a
	  b
	  (foreach p b
	    (setq c
		   (mapcar '(lambda (x)
			      (list (setq c (vlax-curve-getclosestpointto x p)) (distance p c) (_dxf 8 x))
			    )
			   a
		   )
	    )
	    (setq c (car (vl-sort c '(lambda (r j) (< (cadr r) (cadr j))))))
	    (if	(not (equal 0 (cadr c) 1e-3))
	      (progn (setq
		       e (entmakex (list '(0 . "line") (cons 10 p) (cons 11 (car c)) (cons 8 (caddr c))))
		     )
		     ;; This line below creates the right example comment out to get left
		     (setq a (cons e a))
	      )
	    )
	  )
     )
    )
  )
  (princ)
)

 

Edited by ronjonp
*speed improvement
  • Like 1
Link to comment
Share on other sites

  • 6 months later...

is it possible to change this lisp to get Perpendicular line from a Point to Perpendicular line from a BLOCK BASE POINT ?

i mean first select the polyline and then select all blocks and it'll create a perpendicular line to the polyline/line/arc ive selected and draw a line. The lisp above creates the same but i can only select points, not blocks. Leemacs and Emmanuels lisp are working great with points(foo lisp had some errors)

 

i don't know much about lisp codes and all, please help if possible.. Thanks..

Link to comment
Share on other sites

Sure, just change line 17 in my code to ( change "POINT" to "INSERT")

 

(setq pts_ss (ssget (list (cons 0 "INSERT"))))

 

Then you can change the messages if you feel like it.

(princ "\nSelect polyline: ")  ;; it also works for line, spline, ...

(princ "\nSelect Points: ")    ;; it's not points anymore

Link to comment
Share on other sites

9 hours ago, minejash said:

..(foo lisp had some errors)

 

...

Can you elaborate? Is it the fact that only LWPOLYLINES are used?

 

Just guessing but this should do what you want:

(defun c:foo (/ _dxf _sl a b c e p s x)
  ;; RJP » 2019-01-10
  (defun _sl (s) (cond ((= 'pickset (type s)) (vl-remove-if 'listp (mapcar 'cadr (ssnamex s))))))
  (defun _dxf (c e) (cdr (assoc c (entget e))))
  (cond
    ((setq s (_sl (ssget)))
     (foreach x	s
       (if (wcmatch (_dxf 0 x) "CIRCLE,INSERT,POINT")
	 (setq b (cons (_dxf 10 x) b))
	 (and (= 'real (type (vl-catch-all-apply 'vlax-curve-getendparam (list x))))
	      (setq a (cons x a))
	 )
       )
     )
     (and a
	  b
	  (foreach p b
	    (setq c
		   (car	(vl-sort
			  (mapcar
			    '(lambda (x)
			       (list (setq c (vlax-curve-getclosestpointto x p)) (distance p c) (_dxf 8 x))
			     )
			    a
			  )
			  '(lambda (r j) (< (cadr r) (cadr j)))
			)
		   )
	    )
	    (setq e (entmakex (list '(0 . "line") (cons 10 p) (cons 11 (car c)) (cons 8 (caddr c)))))
	    ;; This line below creates the right example comment out to get left
	    ;; (setq a (cons e a))
	  )
     )
    )
  )
  (princ)
)

 

Edited by ronjonp
Link to comment
Share on other sites

@Emmanuel Delay @ronjonp Thank you so much Both of you, Both are working perfect and as i wanted. 

 

@ronjonpThe foo lisp was working before also but it just adds a line to the nearest block insert (not to the line perpendicular),have attached a snap. Thanks now the code is working as i wanted.

foo.JPG

  • Like 1
Link to comment
Share on other sites

  • 1 month later...
27 minutes ago, Nicci said:

Can any of the routines provided here be modified to move a lot of points to a selected polyline at the location where they would intersect perpendicularly.

 

@Nicci - since this thread is kind of old, you might want to tag some of the posters in here to grab their attention.

 

@BlackBox

 

@Emmanuel Delay

 

@ronjonp

Link to comment
Share on other sites

1 hour ago, Nicci said:

Can any of the routines provided here be modified to move a lot of points to a selected polyline at the location where they would intersect perpendicularly.

 

 Try this

 

(defun c:mper ( / ent ss cnt e_lst i_pt c_pt)
  (setq ent (car (entsel "\nSelect Line Entity : ")))
  (cond ( (vl-position (cdr (assoc 0 (entget ent))) '("LWPOLYLINE" "ARC" "LINE" "CIRCLE" "ELLIPSE" "SPLINE"))
          (prompt "\nSelect Points : ")
          (setq ss (ssget '((0 . "POINT"))))
          (repeat (setq cnt (sslength ss))
            (setq i_pt (cdr (assoc 10 (setq e_lst (entget (ssname ss (setq cnt (1- cnt)))))))
                  c_pt (vlax-curve-getclosestpointto ent i_pt)
            )
            (entmod (subst (cons 10 c_pt) (assoc 10 e_lst) e_lst))
          );end_repeat
        )
        ( (alert "Not a Line Entity"))
  );end_cond
  (princ)
);end_defun

 

  • Thanks 1
Link to comment
Share on other sites

@dlanorh Thank you for your response.  I tried your routine and it wont allow me to select my polyline.  I am not very familiar with the language. perhaps this is what @ronjonp is referring to in his comment.

Also, after thinking about it, I would also like to have the option to move points OR text.  

Link to comment
Share on other sites

  • 3 weeks later...

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