Jump to content

Shortest polyline between two flanges


Jozef13

Recommended Posts

Hello everyone,
I am looking for a way to automatically connect necks or flanges with a flexible pipe of a given size, or at least a polyline with a given fillet radius.
For flexible pipes size=radius
DWG attached for clarification

Flexible ducts.dwg

Link to comment
Share on other sites

Here you go. 

(defun c:Wrap (/ int sel ent obj)
  ;;----------------------------------------------------;;
  ;;	Author : Tharwat Al Choufi			;;
  ;; website: https://autolispprograms.wordpress.com	;;
  ;;----------------------------------------------------;;
  (and (or (tblsearch "LAYER" "MF_Flexo")
           (alert "Please create a layer name < MF_Flexo > in prior to process.!")
           )
       (princ "\nSelect center 'polyline' of Flexible duct : ")
       (setq int -1 sel (ssget "_:L" '((0 . "LWPOLYLINE"))))
       (while (setq int (1+ int) ent (ssname sel int))
         (setq obj (vlax-ename->vla-object ent))
         (mapcar (function (lambda (v / o)
                             (setq o (car (vlax-invoke obj 'Offset v)))
                             (vla-put-layer o "MF_Flexo")
                             (vla-put-linetype o "ByLayer")
                             (vla-put-Color o 256)
                           )
                 )
                 '(79.5 -79.5)
         )
       )
  )
  (princ)
) (vl-load-com)

 

  • Thanks 1
Link to comment
Share on other sites

Hey, that's a fun problem to try to solve.

 

I got part of the solution.

- Command DFT (for Draw Flexible Tube)

- Select point 1

- Select point 2

- Select point 3

... as shown on the picture

 

 

;;	https://www.cadtutor.net/forum/topic/79564-shortest-polyline-between-two-flanges/

;; @file  

(defun r2d (r / ) 
	(/ (* r 180.0) pi)
)

(defun d2r (d / ) 
	(* (/ d 180.0) pi)
)

;; midpoint of 2 given points
(defun mid ( pt1 pt2 / )
  (mapcar '(lambda (x y) (+ (* 0.5 x) (* 0.5 y)))
  pt1
  pt2
  )
)

(defun drawLWPoly (lst cls)
 (entmakex (append (list (cons 0 "LWPOLYLINE")
                         (cons 100 "AcDbEntity")
                         (cons 100 "AcDbPolyline")
                         (cons 90 (length lst))
                         (cons 70 cls))
                   (mapcar (function (lambda (p) (cons 10 p))) lst))))
				   
(defun drawLine (p1 p2)
 (entmakex (list (cons 0 "LINE")
                 (cons 10 p1)
                 (cons 11 p2))))


;; command DFT, for Draw Flexible Tube
(defun c:DFT ( / p1 p2 pm p3 duct_diam ang1 ang2 kink1 kink2 pl1 pl2 pl3 fillet1 fillet2)

	(setq p1 (getpoint "\nPoint 1 (right edge of the base): "))
	(setq p2 (getpoint p1 "\nPoint 2 (left edge of the base): "))
	(setq pm (mid p1 p2))
	(setq duct_diam (distance p1 p2))
	;; read angle.  minus 90°, that's the angle of the first vertex of the duct
	(setq ang1 (- (angle p1 p2) (d2r 90.0)))	
	(princ (r2d ang1))
	
	(princ "\nDuct diameter: ")
	(princ duct_diam)
	(princ " - angle: ")
	(princ (r2d ang1))
	
	(setq p3 (getpoint "\nPoint 3: (middle of the top): "))
	
	;; step 1, we need a point perpendicular to p1-p2, length = distance p1-p2
	(setq kink1 (polar pm ang1 duct_diam))
	;; dito for endpoint.  I assume the top is always horizontal
	(setq kink2 (polar p3 (d2r -90.0) duct_diam))
	
	;; We draw 3 lines. 
	(setq pl1 (drawLine pm kink1))
	(setq pl2 (drawLine kink1 kink2))
	(setq pl3 (drawLine kink2 p3))

	;; now fillet 
	(setvar "FILLETRAD" duct_diam)
	(command "_.fillet" pl2 pl1)
	(setq fillet1 (entlast))
	(command "_.fillet" pl2 pl3)
	(setq fillet2 (entlast))
	
	(princ)
	
)

 

flexible_tube.png

  • Like 1
Link to comment
Share on other sites

2 hours ago, Tharwat said:

Here you go. 

(defun c:Wrap (/ int sel ent obj)
  ;;----------------------------------------------------;;
  ;;	Author : Tharwat Al Choufi			;;
  ;; website: https://autolispprograms.wordpress.com	;;
  ;;----------------------------------------------------;;
  (and (or (tblsearch "LAYER" "MF_Flexo")
           (alert "Please create a layer name < MF_Flexo > in prior to process.!")
           )
       (princ "\nSelect center 'polyline' of Flexible duct : ")
       (setq int -1 sel (ssget "_:L" '((0 . "LWPOLYLINE"))))
       (while (setq int (1+ int) ent (ssname sel int))
         (setq obj (vlax-ename->vla-object ent))
         (mapcar (function (lambda (v / o)
                             (setq o (car (vlax-invoke obj 'Offset v)))
                             (vla-put-layer o "MF_Flexo")
                             (vla-put-linetype o "ByLayer")
                             (vla-put-Color o 256)
                           )
                 )
                 '(79.5 -79.5)
         )
       )
  )
  (princ)
) (vl-load-com)

 

Perfect, effective wrapping code. Much, much better than what I actually use.
But my goal is to draw a centreline (polyline) to connect necks or flanges much more efficiently without using auxiliary lines.
Especially when the flanges are rotated against the ortho system.

Link to comment
Share on other sites

My code draws the center line. 

Tharwat's code wraps it.

 

My code should just polyline edit -> join them

  • Agree 1
Link to comment
Share on other sites

11 minutes ago, Emmanuel Delay said:

My code draws the center line. 

Tharwat's code wraps it.

 

My code should just polyline edit -> join them

Great I see :)
Thank you for your code.
It works fine but it is very sensitive to the order of the points as you can see in the attachments and I never know what order to choose to get the right result :)
And in case number 8, the line created is not perpendicular.

Point order sensitivity-1.jpg

Point order sensitivity-2.jpg

Flexible ducts.dwg

Link to comment
Share on other sites

Yeah, as your example showed, my code assumed a vertical ending.
I'll adapt it for different angles.

And yes, it asks for an order of points.  First right edge, then left edge.  

 

Right and left are defined as: point 1 is right, point 2 is left.

Take a line p1-p2.  Now that angle based of the line, turn it 90° clockwise.  In that angle the duct will go away from the base

 

Edited by Emmanuel Delay
Link to comment
Share on other sites

If you can get used of the Right-Left definition, then use this.  It now does any angle

(again: line from right to left, add 90 ° clockwise, that's the direction of the tube/duct)

 

EDIT:

- Oh yes, and I join the lines and arcs to 1 polyline. 

- And I set it to the right layer, color, linetype and lt scale

Then you can use Tharwat's code to make the wrapping

 

(vl-load-com) 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; https://www.cadtutor.net/forum/topic/32405-looking-for-the-join-polyline-lisp-that-is-in-this-forum/?do=findComment&comment=261544
;; Polyline Edit, Join 

(defun c:pj ( / pe ss )
 (setq pe (getvar 'PEDITACCEPT))
 (setvar 'PEDITACCEPT 1)
 (if (setq ss (ssget "_:L" '((0 . "ARC,LINE,LWPOLYLINE"))))
   (command "_.pedit" "_M" ss "" "_J" "" "")
 )
 (setvar 'PEDITACCEPT pe)
 (princ)
)

;; SS is a ssget selection (could be made with ssadd of course) of "ARC,LINE,LWPOLYLINE"...
;;
(defun pj (ss  / pe )
	;; (setq ss (ssget "_:L" '((0 . "ARC,LINE,LWPOLYLINE"))))
	(setq pe (getvar 'PEDITACCEPT))
	(setvar 'PEDITACCEPT 1)
	(if ss
		(command "_.pedit" "_M" ss "" "_J" "" "")
	)
	(setvar 'PEDITACCEPT pe)
	(entlast)		;; return the newly made polyline object
)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; @file  

(defun r2d (r / ) 
	(/ (* r 180.0) pi)
)

(defun d2r (d / ) 
	(* (/ d 180.0) pi)
)

;; midpoint of 2 given points
(defun mid ( pt1 pt2 / )
  (mapcar '(lambda (x y) (+ (* 0.5 x) (* 0.5 y)))
  pt1
  pt2
  )
)

(defun drawLWPoly (lst cls)
 (entmakex (append (list (cons 0 "LWPOLYLINE")
                         (cons 100 "AcDbEntity")
                         (cons 100 "AcDbPolyline")
                         (cons 90 (length lst))
                         (cons 70 cls))
                   (mapcar (function (lambda (p) (cons 10 p))) lst))))
				   
(defun drawLine (p1 p2)
 (entmakex (list (cons 0 "LINE")
                 (cons 10 p1)
                 (cons 11 p2))))


;; command DFT, for Draw Flexible Tube
(defun c:DFT ( / p1 p2 pm p3 p4 p5 duct_diam ang1 ang2 kink1 kink2 pl1 pl2 pl3 fillet1 fillet2 duct)

	(setq p1 (getpoint "\nPoint 1 (right edge of the base): "))
	(setq p2 (getpoint p1 "\nPoint 2 (left edge of the base): "))
	(setq pm (mid p1 p2))
	(setq duct_diam (distance p1 p2))
	;; read angle.  minus 90°, that's the angle of the first vertex of the duct
	(setq ang1 (- (angle p1 p2) (d2r 90.0)))	
	(princ (r2d ang1))
	
	(princ "\nDuct diameter: ")
	(princ duct_diam)
	(princ " - angle: ")
	(princ (r2d ang1))
	
	
	(setq p4 (getpoint "\nPoint 4: (right edge of the end): "))
	(setq p5 (getpoint "\nPoint 5: (left edge of the end): "))
	(setq p3 (mid p4 p5))
	(setq ang2 (- (angle p4 p5) (d2r 90.0)))	

	;;(setq p3 (getpoint "\nPoint 3: (middle of the top): "))
	
	;; step 1, we need a point perpendicular to p1-p2, length = distance p1-p2
	(setq kink1 (polar pm ang1 duct_diam))
	;; dito for endpoint.  I assume the top is always horizontal
	(setq kink2 (polar p3 ang2 duct_diam))
	
	;; We draw 3 lines. 
	(setq pl1 (drawLine pm kink1))
	(setq pl2 (drawLine kink1 kink2))
	(setq pl3 (drawLine kink2 p3))

	;; now fillet 
	(setvar "FILLETRAD" duct_diam)
	(command "_.fillet" pl2 pl1)
	(setq fillet1 (entlast))
	(command "_.fillet" pl2 pl3)
	(setq fillet2 (entlast))
	
	;; Now we'll join these lines and arcs to 1 polyline.  We first put them in a ss selection
	(setq duct (ssadd))
	(ssadd pl1 		duct)
	(ssadd fillet1 	duct)
	(ssadd pl2 		duct)
	(ssadd fillet2 	duct)
	(ssadd pl3 		duct)
	
	(setq duct (pj duct))
	
	;; linetype and scale
	(setq obj (vlax-ename->vla-object duct))	
	(vla-put-layer obj "MF_Flexo")
	(vla-put-color obj 7)		;; 7 = white
	(vla-put-linetype obj "TRACKS")
	(vla-put-linetypescale obj 320)

	(princ)
	
)

 

flexible_tube2.png

Edited by Emmanuel Delay
  • Like 1
Link to comment
Share on other sites

4 hours ago, Emmanuel Delay said:

If you can get used of the Right-Left definition, then use this.  It now does any angle

(again: line from right to left, add 90 ° clockwise, that's the direction of the tube/duct)

 

EDIT:

- Oh yes, and I join the lines and arcs to 1 polyline. 

- And I set it to the right layer, color, linetype and lt scale

Then you can use Tharwat's code to make the wrapping

 

(vl-load-com) 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; https://www.cadtutor.net/forum/topic/32405-looking-for-the-join-polyline-lisp-that-is-in-this-forum/?do=findComment&comment=261544
;; Polyline Edit, Join 

(defun c:pj ( / pe ss )
 (setq pe (getvar 'PEDITACCEPT))
 (setvar 'PEDITACCEPT 1)
 (if (setq ss (ssget "_:L" '((0 . "ARC,LINE,LWPOLYLINE"))))
   (command "_.pedit" "_M" ss "" "_J" "" "")
 )
 (setvar 'PEDITACCEPT pe)
 (princ)
)

;; SS is a ssget selection (could be made with ssadd of course) of "ARC,LINE,LWPOLYLINE"...
;;
(defun pj (ss  / pe )
	;; (setq ss (ssget "_:L" '((0 . "ARC,LINE,LWPOLYLINE"))))
	(setq pe (getvar 'PEDITACCEPT))
	(setvar 'PEDITACCEPT 1)
	(if ss
		(command "_.pedit" "_M" ss "" "_J" "" "")
	)
	(setvar 'PEDITACCEPT pe)
	(entlast)		;; return the newly made polyline object
)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; @file  

(defun r2d (r / ) 
	(/ (* r 180.0) pi)
)

(defun d2r (d / ) 
	(* (/ d 180.0) pi)
)

;; midpoint of 2 given points
(defun mid ( pt1 pt2 / )
  (mapcar '(lambda (x y) (+ (* 0.5 x) (* 0.5 y)))
  pt1
  pt2
  )
)

(defun drawLWPoly (lst cls)
 (entmakex (append (list (cons 0 "LWPOLYLINE")
                         (cons 100 "AcDbEntity")
                         (cons 100 "AcDbPolyline")
                         (cons 90 (length lst))
                         (cons 70 cls))
                   (mapcar (function (lambda (p) (cons 10 p))) lst))))
				   
(defun drawLine (p1 p2)
 (entmakex (list (cons 0 "LINE")
                 (cons 10 p1)
                 (cons 11 p2))))


;; command DFT, for Draw Flexible Tube
(defun c:DFT ( / p1 p2 pm p3 p4 p5 duct_diam ang1 ang2 kink1 kink2 pl1 pl2 pl3 fillet1 fillet2 duct)

	(setq p1 (getpoint "\nPoint 1 (right edge of the base): "))
	(setq p2 (getpoint p1 "\nPoint 2 (left edge of the base): "))
	(setq pm (mid p1 p2))
	(setq duct_diam (distance p1 p2))
	;; read angle.  minus 90°, that's the angle of the first vertex of the duct
	(setq ang1 (- (angle p1 p2) (d2r 90.0)))	
	(princ (r2d ang1))
	
	(princ "\nDuct diameter: ")
	(princ duct_diam)
	(princ " - angle: ")
	(princ (r2d ang1))
	
	
	(setq p4 (getpoint "\nPoint 4: (right edge of the end): "))
	(setq p5 (getpoint "\nPoint 5: (left edge of the end): "))
	(setq p3 (mid p4 p5))
	(setq ang2 (- (angle p4 p5) (d2r 90.0)))	

	;;(setq p3 (getpoint "\nPoint 3: (middle of the top): "))
	
	;; step 1, we need a point perpendicular to p1-p2, length = distance p1-p2
	(setq kink1 (polar pm ang1 duct_diam))
	;; dito for endpoint.  I assume the top is always horizontal
	(setq kink2 (polar p3 ang2 duct_diam))
	
	;; We draw 3 lines. 
	(setq pl1 (drawLine pm kink1))
	(setq pl2 (drawLine kink1 kink2))
	(setq pl3 (drawLine kink2 p3))

	;; now fillet 
	(setvar "FILLETRAD" duct_diam)
	(command "_.fillet" pl2 pl1)
	(setq fillet1 (entlast))
	(command "_.fillet" pl2 pl3)
	(setq fillet2 (entlast))
	
	;; Now we'll join these lines and arcs to 1 polyline.  We first put them in a ss selection
	(setq duct (ssadd))
	(ssadd pl1 		duct)
	(ssadd fillet1 	duct)
	(ssadd pl2 		duct)
	(ssadd fillet2 	duct)
	(ssadd pl3 		duct)
	
	(setq duct (pj duct))
	
	;; linetype and scale
	(setq obj (vlax-ename->vla-object duct))	
	(vla-put-layer obj "MF_Flexo")
	(vla-put-color obj 7)		;; 7 = white
	(vla-put-linetype obj "TRACKS")
	(vla-put-linetypescale obj 320)

	(princ)
	
)

 

flexible_tube2.png

Great,
It works exactly as expected.

I don't want to be ungrateful, but couldn't it be made more efficient by not entering points, but selecting a line (flange), calculating the centre of the line, the length of the line (duct_diam), then the normal vector to the line and the coordinates of the point lying on the normal duct_diam away, (there will be 2 points on each side :)), the same for the other flange and then find out which normals intersect and that will indicate the direction of drawing the axis of the pipe.
It would be 2 clicks instead of 4 :)

Of course, I don't want to waste your time, and the code you already sent me will save me a lot of time anyway.

Thank you very much

Link to comment
Share on other sites

Right now the flanges are not lines.  

They're blocks.

So it's selecting a vertex of the polyline inside a block

 

I'll need to extend this code I wrote a while ago.  It will takes some time

 

 

Link to comment
Share on other sites

8 minutes ago, Emmanuel Delay said:

Right now the flanges are not lines.  

They're blocks.

So it's selecting a vertex of the polyline inside a block

 

I'll need to extend this code I wrote a while ago.  It will takes some time

 

 

Yes, you're right.
That would be my next question, how to select part of the polyline and also inside the block :)

Link to comment
Share on other sites

Yep nentsel will find a pline in a block. Then can work out which segment, then in turn 90 angle and midpoint. (cadr (nentsel)) is pick point.

(entget (car (nentsel)))
Select entity: ((-1 . <Entity name: 62ba0840>) (0 . "LWPOLYLINE") 

 

 

  • Like 1
Link to comment
Share on other sites

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