Jozef13 Posted February 8 Posted February 8 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 Quote
Tharwat Posted February 8 Posted February 8 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) 1 Quote
Emmanuel Delay Posted February 8 Posted February 8 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) ) 1 Quote
Jozef13 Posted February 8 Author Posted February 8 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. Quote
Emmanuel Delay Posted February 8 Posted February 8 My code draws the center line. Tharwat's code wraps it. My code should just polyline edit -> join them 1 Quote
Jozef13 Posted February 8 Author Posted February 8 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. Flexible ducts.dwg Quote
Emmanuel Delay Posted February 8 Posted February 8 (edited) 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 February 8 by Emmanuel Delay Quote
Emmanuel Delay Posted February 9 Posted February 9 (edited) 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) ) Edited February 9 by Emmanuel Delay 1 Quote
Jozef13 Posted February 9 Author Posted February 9 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) ) 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 Quote
Emmanuel Delay Posted February 9 Posted February 9 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 Quote
Jozef13 Posted February 9 Author Posted February 9 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 Quote
BIGAL Posted February 9 Posted February 9 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") 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.