PGia Posted Monday at 11:25 AM Posted Monday at 11:25 AM Hi again. This may also happen to others: sometimes I have two polylines and I need to get something like a common parallel to both. A sort of hybrid parallel from the original two. Is it possible that this topic has been discussed in the history of this forum and there is a LISP to solve this problem? Thanks in advance. Quote
mhupp Posted Monday at 02:08 PM Posted Monday at 02:08 PM (edited) Posting a drawing would help to be more clear with what your asking for. but maybe this is what your looking for. PAV Edited Monday at 02:08 PM by mhupp 1 Quote
PGia Posted Monday at 03:13 PM Author Posted Monday at 03:13 PM 1 hour ago, mhupp said: Posting a drawing would help to be more clear with what your asking for. but maybe this is what your looking for. PAV This? Quote
PGia Posted Monday at 03:28 PM Author Posted Monday at 03:28 PM (edited) Perhaps the most appropriate description is to obtain the axis between 2 irregular polylines Edited Monday at 03:36 PM by PGia Quote
Nikon Posted Monday at 04:04 PM Posted Monday at 04:04 PM (edited) 37 minutes ago, PGia said: Perhaps the most appropriate description is to obtain the axis between 2 irregular polylines pltools.lsp centerPline.LSP Edited Monday at 04:06 PM by Nikon 1 Quote
PGia Posted Monday at 04:47 PM Author Posted Monday at 04:47 PM 41 minutes ago, Nikon said: pltools.lsp 201.88 kB · 2 downloads centerPline.LSP 10 kB · 2 downloads @NikonThanks for the code. I tried it. But it only works sometimes. And if the polylines' first point coincides with the last, it doesn't work. Is it possible that I'm doing something wrong? Quote
PGia Posted Monday at 04:50 PM Author Posted Monday at 04:50 PM 52 minutes ago, pkenewell said: Look into this post for ideas: @pkenewell Thanks for help. I downloaded the latest code from link and loaded it, but it doesn't seem to do anything. I probably don't understand how it works. Quote
PGia Posted Monday at 05:04 PM Author Posted Monday at 05:04 PM I attach an example Example.dwg Quote
Nikon Posted Monday at 05:51 PM Posted Monday at 05:51 PM 1 hour ago, PGia said: I tried it. But it only works sometimes. And if the polylines' first point coincides with the last, it doesn't work. Is it possible that I'm doing something wrong? The code does not work correctly with polylines that have a large number of segments. Example1.dwg Quote
pkenewell Posted Monday at 05:53 PM Posted Monday at 05:53 PM (edited) 1 hour ago, PGia said: Thanks for help. I downloaded the latest code from link and loaded it, but it doesn't seem to do anything. I probably don't understand how it works. The "MC" command by roy437 works for me on your example drawing. You have to set the point resolution (prompt for "Specify Length for arc(ds)") to improve the results. I used 0.1 for pretty good results. Edited Monday at 05:55 PM by pkenewell Quote
PGia Posted Monday at 06:50 PM Author Posted Monday at 06:50 PM 54 minutes ago, pkenewell said: The "MC" command by roy437 works for me on your example drawing. You have to set the point resolution (prompt for "Specify Length for arc(ds)") to improve the results. I used 0.1 for pretty good results. @pkenewell Thank you very much. I finally got it working. In my case, I set the "length of arcs" to 1. And it worked. But I think the resulting axis isn't very geometrically rigorous. I've attached an example image: -The polyline created by the command is shown in green. -The correct geometry of the axis is shown in dashed red. I think there should be a more geometrically rigorous solution in some older Lisp. Is it possible? Does anyone know of one? Quote
mhupp Posted Monday at 08:35 PM Posted Monday at 08:35 PM (edited) Select both polylines find the polyline that has the most vertex Then process those vertex with vlax-curve-getClosestPointTo store the mid point of vertex and closest point in a list entmake new polyline with list points. Seems to work well tho will need to test if you have open or closed polylines. defaults to closed tho i don't think its quite the mid / avg path ;;----------------------------------------------------------------------------;; ;; CLOSE POLY AVERAGE, Finds the mid point avg between close polylines donut shape (defun c:CLOSEPOLYAVG (/ sel1 sel2 ent1 ent2 cnt1 cnt2 main other i ptv ptc mid pts) (defun c:CPA () (C:CLOSEPOLYAVG)) (defun midpt (p1 p2) (mapcar '(lambda (a b) (/ (+ a b) 2.0)) p1 p2) ) (setq sel1 (entsel "\nSelect First close Polyline: ")) (setq sel2 (entsel "\nSelect Second closed Polyline: ")) (if (and sel1 sel2) (progn (setq ent1 (vlax-ename->vla-object (car sel1)) ent2 (vlax-ename->vla-object (car sel2)) cnt1 (fix (vlax-curve-getEndParam ent1)) cnt2 (fix (vlax-curve-getEndParam ent2)) ) (if (> cnt1 cnt2) (setq main ent1 other ent2) (setq main ent2 other ent1) ) (setq pts '()) (setq i 0) (while (<= i (fix (vlax-curve-getEndParam main))) (setq ptv (vlax-curve-getPointAtParam main i)) (setq ptc (vlax-curve-getClosestPointTo other ptv)) (setq mid (midpt ptv ptc)) (setq pts (append pts (list mid))) (setq i (1+ i)) ) (entmake (append (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") (cons 90 (length pts)) '(70 . 1) ;; closed ) (mapcar '(lambda (p) (cons 10 p)) pts) ) ) (princ "\nNew midpoint polyline created.") ) (princ "\nSelection error.") ) (princ) ) Edited Tuesday at 03:15 AM by mhupp 1 Quote
PGia Posted Tuesday at 06:33 PM Author Posted Tuesday at 06:33 PM Thanks a lot, @mhupp I'll try your code. Quote
PGia Posted yesterday at 12:10 PM Author Posted yesterday at 12:10 PM (edited) On 10/20/2025 at 10:35 PM, mhupp said: Select both polylines find the polyline that has the most vertex Then process those vertex with vlax-curve-getClosestPointTo store the mid point of vertex and closest point in a list entmake new polyline with list points. Seems to work well tho will need to test if you have open or closed polylines. defaults to closed tho i don't think its quite the mid / avg path ;;----------------------------------------------------------------------------;; ;; CLOSE POLY AVERAGE, Finds the mid point avg between close polylines donut shape (defun c:CLOSEPOLYAVG (/ sel1 sel2 ent1 ent2 cnt1 cnt2 main other i ptv ptc mid pts) (defun c:CPA () (C:CLOSEPOLYAVG)) (defun midpt (p1 p2) (mapcar '(lambda (a b) (/ (+ a b) 2.0)) p1 p2) ) (setq sel1 (entsel "\nSelect First close Polyline: ")) (setq sel2 (entsel "\nSelect Second closed Polyline: ")) (if (and sel1 sel2) (progn (setq ent1 (vlax-ename->vla-object (car sel1)) ent2 (vlax-ename->vla-object (car sel2)) cnt1 (fix (vlax-curve-getEndParam ent1)) cnt2 (fix (vlax-curve-getEndParam ent2)) ) (if (> cnt1 cnt2) (setq main ent1 other ent2) (setq main ent2 other ent1) ) (setq pts '()) (setq i 0) (while (<= i (fix (vlax-curve-getEndParam main))) (setq ptv (vlax-curve-getPointAtParam main i)) (setq ptc (vlax-curve-getClosestPointTo other ptv)) (setq mid (midpt ptv ptc)) (setq pts (append pts (list mid))) (setq i (1+ i)) ) (entmake (append (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") (cons 90 (length pts)) '(70 . 1) ;; closed ) (mapcar '(lambda (p) (cons 10 p)) pts) ) ) (princ "\nNew midpoint polyline created.") ) (princ "\nSelection error.") ) (princ) ) Thanks again for your code, @mhupp It seems that the differences in the turning zones between the resulting geometry and the expected geometry persist. I must say that the goal is to obtain an axis that remains equidistant from the reference polylines at all times. I thought this problem would easily find a solution here. Maybe I was wrong Edited yesterday at 12:12 PM by PGia Quote
mhupp Posted yesterday at 01:04 PM Posted yesterday at 01:04 PM (edited) like i said its not really the avg per say because its missing data points. should probably use the larger/longer poly to pull points from (or maybe both and avg it out). The blue line is suffering from not enough detail since its only calculating off the vertex. i can't test right now but see if the selecting order changes anything. Also change the following and should get a better path. tho it will create a poly with 10x the vertex of selected one. (setq i (+ i 0.1)) Edited yesterday at 01:10 PM by mhupp Quote
lrm Posted yesterday at 02:15 PM Posted yesterday at 02:15 PM Here's a simpe solution that doesn't use LISP. Change the elevation of one of the polylines to 1.0 then use the loft command to create asurface. Section the resulting surface with an XY plane at 0,0,0.5. 1 3 Quote
PGia Posted yesterday at 04:31 PM Author Posted yesterday at 04:31 PM 2 hours ago, lrm said: Here's a simpe solution that doesn't use LISP. Change the elevation of one of the polylines to 1.0 then use the loft command to create asurface. Section the resulting surface with an XY plane at 0,0,0.5. Thanks, @lrm It seems your method relies on there being pairs of points close together between both polylines. But when several points accumulate on one of them and don't find a corresponding point on the other, the calculated axis deviates from the center, and the method loses consistency. To keep these cases under control, I think it is best to manage them using a Lisp. But maybe I'm wrong Quote
mhupp Posted yesterday at 06:35 PM Posted yesterday at 06:35 PM See what this does. https://www.cadtutor.net/forum/topic/14213-lisp-to-create-polyline-between-polylines/#findComment-117973 1 Quote
SLW210 Posted 6 hours ago Posted 6 hours ago You can try this...I am not sure how accurate it will be for you, but 100-500 sample size looked pretty good on your drawing, you can change the default, but I kept it at 50 for myself. ;;; Draw a polyline centered between two selected polylines (can be dissimilar/irregular). ;;; ;;; https://www.cadtutor.net/forum/topic/98778-hybrid-parallel/#findComment-676800 ;;; ;;; By SLW210 (a.k.a. Steve Wilson) ;;; (defun c:DrawCl (/ pl1 pl2 num-pts len1 n dist step pt1 pt2 midpt pts) (vl-load-com) ;; Select first polyline (setq pl1 (car (entsel "\nSelect first polyline: "))) (if (not (and pl1 (= (cdr (assoc 0 (entget pl1))) "LWPOLYLINE"))) (progn (princ "\nInvalid first selection.") (exit)) ) ;; Select second polyline (setq pl2 (car (entsel "\nSelect second polyline: "))) (if (not (and pl2 (= (cdr (assoc 0 (entget pl2))) "LWPOLYLINE"))) (progn (princ "\nInvalid second selection.") (exit)) ) ;; Set number of sample points to use (it uses last number entered, default is 50) (if (not *CL_lastNumPts*) (setq *CL_lastNumPts* 50)) (setq num-pts (getint (strcat "\nEnter number of sample points <" (itoa *CL_lastNumPts*) ">: ") ) ) (if (null num-pts) (setq num-pts *CL_lastNumPts*)) (setq *CL_lastNumPts* num-pts) ;; Calculate (setq len1 (vlax-curve-getDistAtParam pl1 (vlax-curve-getEndParam pl1))) (setq step (/ len1 num-pts)) (setq dist 0.0 pts '() ) ;; Midpoint list (repeat (1+ num-pts) (setq pt1 (vlax-curve-getPointAtDist pl1 dist)) (setq pt2 (vlax-curve-getClosestPointTo pl2 pt1)) (if (and pt1 pt2) (setq pts (cons (mapcar '(lambda (a b) (/ (+ a b) 2.0)) pt1 pt2) pts)) ) (setq dist (+ dist step)) ) ;; Create polyline (if pts (progn (setq pts (reverse pts)) (entmake (append (list (cons 0 "LWPOLYLINE") (cons 100 "AcDbEntity") (cons 100 "AcDbPolyline") (cons 90 (length pts)) (cons 70 0) ) (mapcar '(lambda (p) (cons 10 p)) pts) ) ) (princ "\nCenterline drawn accurately between polylines.") ) (princ "\nNo points generated — check polylines.") ) (princ) ) (princ "\nType DrawCl to draw a centerline between two polylines.") (princ) That said, I just tried Lee Mac's cPoly in mhupp's last link posted, seems to be similar results to mine if you adjust the sample points. I haven't checked the others yet, I'll run through them if I get time. I originally made mine with the command function, then changed it to entmake, pretty sure the accuracy is the same, it just had a lot of "Specify next point or [Arc/Close/Halfwidth/Length/Undo/Width]:" in the commandline for each sample. P.S. Mine should take into account reversed polylines. At the same sample size, mine and Lee Mac's seem to be exactly the same on your drawing. I still have to do on mine, set a layer and linetype option in the code. 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.