Leaderboard
Popular Content
Showing content with the highest reputation on 11/19/2025 in all areas
-
I added extra checks on every vertex like @PGia suggested two weeks ago. Those I added to the offset-loop and it gives the best of both worlds. Every point that is calculated should be the exact middle because the offset is the same on both sides. Still not perfect, but pretty close I think. ;| ; Calculate centerline between two polylines - dexus ; Function checks intersections of the offsets of two lines to create a middle/avarage line. |; (defun c:cl (/ ent1 ent2 loop maxlen offset offsetdistance pts s1 s2 ss start LM:ProjectPointToLine LM:intersections _addPoints _avarageAngle _cornerOffset _doOffset _getAnglesAtParam _getLength _polyline _side _wait) ;| ; Draw Polyline - dexus ; Draw a polyline from a list of points, but filter out colinear points ; @Param lst list of points ; @Returns ename of polyline |; (defun _polyline (lst / prev pts) (while lst (cond ((and (cdr lst) prev (null (inters prev (car lst) prev (cadr lst))))) ((setq pts (cons (cons 10 (setq prev (car lst))) pts))) ) (setq lst (cdr lst)) ) (entmakex (append (list (cons 0 "LWPOLYLINE") (cons 100 "AcDbEntity") (cons 100 "AcDbPolyline") (cons 90 (length pts)) (cons 8 (getvar 'clayer)) (cons 70 0) ) (reverse pts) ) ) ) (defun _side (pline pnt / cpt end target der) (setq cpt (vlax-curve-getClosestPointTo pline pnt) ; https://www.theswamp.org/index.php?topic=55685.msg610429#msg610429 end (vlax-curve-getEndParam pline) target (vlax-curve-getParamAtPoint pline cpt) der (if (and (equal target (fix target) 1e-8) (or (vlax-curve-isClosed pline) (and (not (equal (vlax-curve-getStartParam pline) target 1e-8)) (not (equal end target 1e-8))) ) ) (mapcar '- (polar cpt (angle '(0 0) (vlax-curve-getFirstDeriv pline (rem (+ target 1e-3) end))) 1.0) (polar cpt (angle (vlax-curve-getFirstDeriv pline (rem (+ (- target 1e-3) end) end)) '(0 0)) 1.0) ) (vlax-curve-getFirstDeriv pline target) ) ) (minusp (sin (- (angle cpt pnt) (angle '(0.0 0.0) der)))) ) ;; Intersections - Lee Mac ;; mod - [int] acextendoption enum of intersectwith method (defun LM:intersections ( ob1 ob2 mod / lst rtn ) (if (and (vlax-method-applicable-p ob1 'intersectwith) (vlax-method-applicable-p ob2 'intersectwith) (setq lst (vlax-invoke ob1 'intersectwith ob2 mod)) ) (repeat (/ (length lst) 3) (setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn) lst (cdddr lst)) ) ) (reverse rtn) ) (defun _getLength (ent) (- (vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent)) (vlax-curve-getDistAtParam ent (vlax-curve-getStartParam ent)) ) ) (defun _wait (msec) (not ( (lambda (start) (while (< (- (getvar 'millisecs) start) msec)) ) (getvar 'millisecs) ) ) ) (defun _addPoints (lst ent pts / len) (setq len (_getLength ent)) (setq lst (mapcar (function (lambda (pt) (list (/ (vlax-curve-getDistAtPoint ent pt) len) pt))) lst)) (setq pts (append lst pts)) ; Animation ; (setq pts (vl-sort pts (function (lambda (a b) (< (car a) (car b)))))) ; (redraw) ; ( ; (lambda (lst) ; (while (cadr lst) ; (grdraw (cadar lst) (cadadr lst) 3) ; (setq lst (cdr lst)) ; ) ; ) ; pts ; ) ; (vla-update ent) ; (_wait 40) ; End animation pts ) (defun _doOffset (offset / te1 te2 lst rtn) ; Global vars: pts ent1 ent2 s1 s2 (setq rtn (cond ((equal offset 0.0 1e-4) (if (setq lst (LM:intersections ent1 ent2 acExtendNone)) (setq pts (_addPoints lst ent1 pts)) ) lst ) ( (or ; Make offset (vl-catch-all-error-p (setq te1 (vl-catch-all-apply 'vlax-invoke (list ent1 'Offset (if s1 offset (- offset)))))) (vl-catch-all-error-p (setq te2 (vl-catch-all-apply 'vlax-invoke (list ent2 'Offset (if s2 offset (- offset)))))) (vla-put-color (car te1) 252) (vla-put-color (car te2) 252) ) (princ "\nOffset failed. ") nil ) ((setq lst (LM:intersections (car te1) (car te2) acExtendNone)) (setq pts (_addPoints lst (car te1) pts)) lst ) ) ) (if (and te1 (not (vl-catch-all-error-p te1))) (mapcar 'vla-delete te1)) (if (and te2 (not (vl-catch-all-error-p te2))) (mapcar 'vla-delete te2)) rtn ) ;| ; Project Point onto Line - Lee Mac ; @Param pt point to project ; @Param p1 first point of line ; @Param p2 second point of line ; @Returns projected point |; (defun LM:ProjectPointToLine ( pt p1 p2 / nm ) (setq nm (mapcar '- p2 p1) p1 (trans p1 0 nm) pt (trans pt 0 nm)) (trans (list (car p1) (cadr p1) (caddr pt)) nm 0) ) (defun _getAnglesAtParam (ent pa / ang1 ang2) (if (and (vlax-curve-isClosed ent) (= pa 0)) ; Special case for closed Polyline (list (setq ang1 (vlax-curve-getFirstDeriv ent 1e-14)) (setq ang2 (vlax-curve-getFirstDeriv ent (- (fix (vlax-curve-getEndParam ent)) 1e-14))) ) (list (setq ang1 (vlax-curve-getFirstDeriv ent (+ pa 1e-14))) (setq ang2 (vlax-curve-getFirstDeriv ent (- pa 1e-14))) ) ) (setq ang1 (angle '(0 0 0) ang1)) (setq ang2 (angle '(0 0 0) ang2)) (list ang1 (* (+ ang1 ang2) 0.5) ang2) ) ;| ; Avarage Angle - dexus ; Get angle of a line between two angles ; @Param ang1 real - Angle in radians ; @Param ang2 real - Angle in radians ; @Returns real - Angle in radians |; (defun _avarageAngle (ang1 ang2) (if (< (rem (+ ang1 pi) (+ pi pi)) (rem (+ ang2 pi) (+ pi pi)) ) (+ (* (- ang2 ang1) 0.5) ang1) (+ (* (- ang1 ang2) 0.5) ang2) ) ) ;| ; Calculate exact offset distance on a corner - dexus ; pt1 - Point on corner ; pt2 - Point on other side ; pt3 - Center for bisector ; pt4 - Target for corner of the offset ; pt5 - Find perpendicular point for offset distance ; / ; / ; -------- pt1 pt5 ; \ / ; pt4 ; \ ; ---- pt3 ----- pt2 ----- ; ; @Param ent1 Line to check corners ; @Param ent2 Opposing line ; @Returns List of offset distances (pt1 -> pt5) to calculate |; (defun _cornerOffset (ent1 ent2 / ang1 ang2 ang3 index pt1 pt2 pt3 pt4 pt5 rtn tmp vertex) (setq vertex (fix (vlax-curve-getEndParam ent1)) halfPi (* pi 0.5) index 0) (repeat vertex (and (setq pt1 (vlax-curve-getPointAtParam ent1 index)) ; Point on corner (setq ang1 (_getAnglesAtParam ent1 index)) ; Angles of pt1 (setq tmp ; Temp line for finding the angle on the other side (entmakex (list '(0 . "line") (cons 10 (polar pt1 (+ (cadr ang1) halfPi) maxlen)) (cons 11 (polar pt1 (- (cadr ang1) halfPi) maxlen)) ) ) ) (setq pt2 (car (LM:intersections (vlax-ename->vla-object tmp) ent2 acExtendNone))) ; Point on other side (setq ang2 (_getAnglesAtParam ent2 (vlax-curve-getParamAtPoint ent2 pt2))) ; Angle of pt2 (if (equal (rem (car ang1) pi) (rem (car ang2) pi) 1e-9) ; Is parallel? (and (setq pt3 (mapcar (function (lambda (a b) (* (+ a b) 0.5))) pt1 pt2)) ; Midpoint (setq ang3 (car ang1)) ; Same angle als ang1 ) (and (setq pt3 (inters pt1 (polar pt1 (car ang1) 1) pt2 (polar pt2 (car ang2) 1) nil)) ; Find center for bisector (setq ang3 (_avarageAngle (angle pt1 pt3) (angle pt2 pt3))) ; Angle of bisector ) ) (setq pt4 (inters pt3 (polar pt3 ang3 1) pt1 (polar pt1 (+ (cadr ang1) halfPi) 1) nil)) ; Find target for corner of the offset (setq pt5 (LM:ProjectPointToLine pt4 pt1 (polar pt1 (+ (car ang1) halfPi) maxlen))) ; Find perpendicular point for offset distance (setq rtn (cons (distance pt1 pt5) rtn)) ; Return offset distance ) (if (entget tmp) (entdel tmp)) (setq index (1+ index)) ) rtn ) (if (not (while (cond ((not (setq ss (ssget '((0 . "LWPOLYLINE"))))) (princ "\nNothing selected. Try again...\n") ) ((/= (sslength ss) 2) (princ "\nSelect 2 polylines! Try again...\n") ) ((and (setq ent1 (ssname ss 0)) (setq ent2 (ssname ss 1)) (setq ent1 (vlax-ename->vla-object ent1)) (setq ent2 (vlax-ename->vla-object ent2)) ) nil ; Stop loop ) ) ) ) (progn (setq s1 (_side ent1 (vlax-curve-getStartPoint ent2))) (setq s2 (_side ent2 (vlax-curve-getStartPoint ent1))) (setq maxlen (* 1.1 (max (_getLength ent1) (_getLength ent2) (distance (vlax-curve-getStartPoint ent1) (vlax-curve-getStartPoint ent2))))) (setq offsetdistance (/ maxlen 1024.0)) (if (LM:intersections ent1 ent2 acExtendNone) (setq offset (- maxlen)) (setq offset 0.0) ) (mapcar '_doOffset (_cornerOffset ent1 ent2)) (mapcar '_doOffset (_cornerOffset ent2 ent1)) (while (progn (setq loop (cond ((> offset maxlen) nil) ((_doOffset offset) (setq start t)) ((not start) t) (start nil) ) ) (setq offset (+ offset offsetdistance)) loop ) ) (if pts (_polyline (mapcar 'cadr (vl-sort pts (function (lambda (a b) (< (car a) (car b))))))) ) ) ) (redraw) (princ) )5 points
-
I think you're doing a very good job. PS: The animation in the GIF doesn't look the same as the one in the code.2 points
-
I'm still sorting an attempt at the Bowyer–Watson version, but first I am trying to sort a few that are getting close. The export CSV and import a centerline is very close, but on the AxisExample .dwg it has a zig-zag glitch. I have one that draws the bisector lines that's close, but still misses the midpoint coming around those turns. I do have the one that appears very accurate on bends in one direction and the bends in the opposite direction depending on pick order. This would work if the AxisExample.dwg was in separate sections at the turns, maybe. I get a error: bad argument type: fixnump: nil with the AxisExample.dwg and some other errors on the original Example.dwg (Two vertices were added to a 2D pline (0) which had no vertices. and error: bad argument type: numberp: nil ) though the simple ones it draws the centerline with @marko_ribar's version. Every one of these fall short on the OPs AxisExample drawing, most in the same areas. So, I will probably keep at this for a while to see how close I can get it. For sure, nearly everyone of these are as good as and many much better than, the currently available solutions in AutoCAD. The solution suggested by Autodesk, PathAverage.lsp by Kent Cooper, fails miserably on most of the OP's examples, though seems to work in most cases and needs the polylines in the same direction. I still have work to do for my paying job, but hopefully I can bang out something soon.2 points
-
This is a very simple test to make everything is inside the code including the images. next step would be to look at the Lee-mac example and use vectors rather than slides. Thanks to RLX for convert DCL. ; https://www.cadtutor.net/forum/topic/98827-the-coordinates-of-the-trapezoid/page/2/#comment-677242 ; Fill in 4 image dcl with vector images ; simple working example by AlanH Nov 2025 (setq imgslst (list (list (list 19 222 128 222 7) (list 128 222 128 114 7) (list 128 114 19 114 7) (list 19 114 19 222 7)) (list (list 37 202 119 202 7) (list 119 202 139 120 7) (list 139 120 17 120 7) (list 17 120 37 202 7)) (list (list 36 203 120 203 7) (list 120 203 101 161 7) (list 141 119 16 119 7) (list 16 119 36 203 7)(list 101 161 141 119 7)) (list (list 38 200 118 200 7) (list 118 200 99 160 7) (list 138 120 18 120 7) (list 55 168 38 200 7)(list 99 160 138 120 7)(list 55 168 18 120 7)) ) ) (defun VECTOR4 (dclkey imglst / i j) (setq i (/ (dimx_tile DCLKEY) 151.) j (/ (dimy_tile DCLKEY) 326.)) (start_image DCLKEY) (fill_image 0 0 (dimx_tile DCLKEY)(dimy_tile DCLKEY) -2) (foreach x imglst (vector_image (fix (* (car x) i))(fix (* (cadr x) j))(fix (* (caddr x) i))(fix (* (cadddr x) j))(last x)) ) (end_image) (princ) ) (defun makedcl ( / ) (setq dcl (vl-filename-mktemp nil nil ".dcl") ) (setq des (open dcl "w") ) (foreach x '( "// dd2x2 dialogue. Used by the d2x2 command in dd2x2.lsp." "// Called from the AutoCAD Release 12 Standard Menu." "dd2x2: dialog {" " label = \"Pick shape\";" " : column {" " : row {" " : image_button {" " key = \"22sq1\";" " width = 15;" " aspect_ratio = 1.0;" " color = 0;" " allow_accept = true;" " }" " : image_button {" " key = \"22sq2\";" " width = 15;" " aspect_ratio = 1.0;" " color = 0;" " allow_accept = true;" " }" " }" " : row {" " : image_button {" " key = \"22sq3\";" " width = 15;" " aspect_ratio = 1.0;" " color = 0;" " allow_accept = true;" " }" " : image_button {" " key = \"22sq4\";" " width = 15;" " aspect_ratio = 1.0;" " color = 0;" " allow_accept = true;" " }" " }" " }" "ok_cancel;" "}" ) (write-line x des ) ); foreach (close des) (princ) ) (defun wow ( / x ans dcl keynum imgsitem dclkey ) (makedcl) (setq dcl_id (load_dialog dcl)) (if (not (new_dialog "dd2x2" dcl_id) ) (exit) ) (setq keynum 1) (repeat 4 (setq imgsitem (nth (- keynum 1) imgslst)) (setq dclkey (strcat "22sq" (rtos keynum 2 0))) (VECTOR4 dclkey imgsitem) (setq keynum (1+ keynum)) ) (action_tile "22sq1" "(setq ans $key)(done_dialog)") (action_tile "22sq2" "(setq ans $key)(done_dialog)") (action_tile "22sq3" "(setq ans $key)(done_dialog)") (action_tile "22sq4" "(setq ans $key)(done_dialog)") (action_tile "accept" "(setq ans $key)(done_dialog)") (action_tile "cancel" "(setq ans $key)(done_dialog)") (start_dialog) (unload_dialog dcl_id) (vl-file-delete dcl) (princ (strcat "\nsq picked = " ans)) (princ) ) (wow)2 points
-
I made some simple shapes and used Vectorize to do just that, here are some samples. next step is to look at Lee-Mac example. Only read the vectors pattern in the following code. ;******************************************************************************** ; Function to draw a vector image within a dialogue Image tile or Image Button. * ; Argument: 'DCLKEY' - the dcl key of the image tile/button to be filled. * ; Do NOT edit the dcl dimension text below, this is needed by Vectorize. * ;******************************************************************************** ; Compiled for dcl dimensions of width,24.92, height,24.97, * ;******************************************************************************** (defun VECTOR1 (DCLKEY / i j) (setq i (/ (dimx_tile DCLKEY) 151.) j (/ (dimy_tile DCLKEY) 326.)) (start_image DCLKEY) (fill_image 0 0 (dimx_tile DCLKEY)(dimy_tile DCLKEY) -15) (foreach x '((19 222 128 222 7) (128 222 128 114 7) (128 114 19 114 7) (19 114 19 222 7)) (vector_image (fix (* (car x) i))(fix (* (cadr x) j))(fix (* (caddr x) i))(fix (* (cadddr x) j))(last x))) (end_image) (princ) ) (defun VECTOR2 (DCLKEY / i j) (setq i (/ (dimx_tile DCLKEY) 151.) j (/ (dimy_tile DCLKEY) 326.)) (start_image DCLKEY) (fill_image 0 0 (dimx_tile DCLKEY)(dimy_tile DCLKEY) -15) (foreach x '((37 202 119 202 7) (119 202 139 120 7) (139 120 17 120 7) (17 120 37 202 7)) (vector_image (fix (* (car x) i))(fix (* (cadr x) j))(fix (* (caddr x) i))(fix (* (cadddr x) j))(last x))) (end_image) (princ) ) (defun VECTOR3 (DCLKEY / i j) (setq i (/ (dimx_tile DCLKEY) 151.) j (/ (dimy_tile DCLKEY) 326.)) (start_image DCLKEY) (fill_image 0 0 (dimx_tile DCLKEY)(dimy_tile DCLKEY) -15) (foreach x '((36 203 120 203 7) (120 203 101 161 7) (141 119 16 119 7) (16 119 36 203 7) (101 161 141 119 7)) (vector_image (fix (* (car x) i))(fix (* (cadr x) j))(fix (* (caddr x) i))(fix (* (cadddr x) j))(last x))) (end_image) (princ) ) (defun VECTOR4 (DCLKEY / i j) (setq i (/ (dimx_tile DCLKEY) 151.) j (/ (dimy_tile DCLKEY) 326.)) (start_image DCLKEY) (fill_image 0 0 (dimx_tile DCLKEY)(dimy_tile DCLKEY) -15) (foreach x '((38 200 118 200 7) (118 200 99 160 7) (138 120 18 120 7) (55 168 38 200 7) (99 160 138 120 7) (55 168 18 120 7)) (vector_image (fix (* (car x) i))(fix (* (cadr x) j))(fix (* (caddr x) i))(fix (* (cadddr x) j))(last x))) (end_image) (princ) ) (setq imgslst (list (list (list 19 222 128 222 7) (list 128 222 128 114 7) (list 128 114 19 114 7) (list 19 114 19 222 7)) (list (list 37 202 119 202 7) (list 119 202 139 120 7) (list 139 120 17 120 7) (list 17 120 37 202 7)) (list (list 36 203 120 203 7) (list 120 203 101 161 7) (list 141 119 16 119 7) (list 16 119 36 203 7)(list 101 161 141 119 7)) (list (list 38 200 118 200 7) (list 118 200 99 160 7) (list 138 120 18 120 7) (list 55 168 38 200 7)(list 99 160 138 120 7)(list 55 168 18 120 7)) ) ) Watch this psace. VECTORIZE.lsp2 points
-
From what I quickly look into on the Dassault Systems (SolidWorks) site, among other changes for SolidWorks 2025 API, there was a change in the methods for saving a drawing. My WAG is that's where the VBA is failing on SolidWorks 2025, could be another change as well.1 point
-
1 point
-
How far should the centers of the radius-10 circles be from the center? In other words, how do you place the tabs (or whatever you call those circular protrusions)? It looks like the left and right sides of the central tab are different. Should they be symmetric? Once you place the tab circles, you should be able to draw the radius-4 circles as tangent to two of the tabs. Then it's just a matter of trimming. Here's what I got with the tabs placed on the diameter-80 arc:1 point
-
Yeah Lee's code is brilliant as usual. Nice way the image changes. Two things, Use Rlx convert DCL to lsp so dcl code is in lisp. Will have a think about vectors have some code some where.Convert dcl 2 lisp rlx.lsp1 point
-
My $0.05 you can draw any shape you want wether it be some form of trapezoid or a shape with 30 sides. It just comes down to writing code that matches the desired shape, Normal trapezoid length, height, angle Dbl angle length, height, angle1, angle2 Indented length, height, angle1, angle2, angle3 And so on., just ask which one you want first. You can even pop a image choice of what you want. Don't have trapezoids as images. Then for me pop a dcl for matching input. Ps @mhupp you don't have to put the AHlstbox in the code can use if (not ahlstbox)(Load "ahlstbox.lsp")) ; will load lisp code on the fly if not already loaded.1 point
-
Here I've revised Helmut's code and made it faster. ;; ; ;; Pathfinding with the A* algorithm by ymg 22/07/2024 ; ;; ; ;; Revised a prog by HELMUT SCHRÖDER - heschr@gmx.de - 2014-09-14 ; ;; found at Cadtutor.net ; ;; ; ;; Kept the same format for edges list but added lines as valid choice ; ;; Format: (((x1 y1) (x2 y2)) (((x2 y2) (x3 y3))....(xn yn))) ; ;; ; ;; The user is asked to pick a start and an endpoint. ; ;; The program will find the shortest path in a network of connected ; ;; polylines and/or lines and draw a new polyline representing the result. ; ;; ; ;; Two lists of nodes openlst and closelst are created from the above ; ;; mentionned edges list. The format of a node list is: ; ;; (((Point) (Prev Point) Cumulated_Distance Estimated_Total_Distance)...) ; ;; ; ;; Main change from origina are: ; ;; - cons the list instead of append ; ;; - vl-sort the openlist instead of the quicksort ; ;; - Replaced and renamed some vars and subroutine. ; ;; - Added fuzz 1e-4 to all points comparison ; ;; - Change the get_path function ; ;; - Added line as possible edges ; ;; - Added an error handler ; ;; - Added a timer to the search portion of the program ; ;; ; ;; The above changes amounted to an acceleration of about 4x from the ; ;; original program. ; ;; : ;; If you compile this program to a .fas you'll get more than 10x faster. ; ;; ; (defun c:A* ( / ssl ssp i edges startp endp openlst closelst found acdoc Edgelay Pathlay Pathcol Pathlwt) (vl-load-com) ; Changes values of following 4 global variables to suit your need. ; (setq Edgelay "Edges" Pathlay "Path" Pathcol 1 ; 1=Red 2=Yellow etc. ; Pathlwt 70 ; lineweight for path 0.7mm ; ) (or acdoc (setq acdoc (vla-get-activedocument (vlax-get-acad-object)))) (set_errhandler '("CLAYER" "OSMODE" "CMDECHO")) (setvar 'CMDECHO 0) (setvar 'OSMODE 1) (if (setq ssp (ssget '"X" (list (cons 0 "LWPOLYLINE") (cons 8 Edgelay)))) (foreach en (mapcar (function cadr) (ssnamex ssp)) (setq edges (append edges (mk_edge (listpol2d en)))) ) ) (if (setq ssl (ssget '"X" (list (cons 0 "LINE") (cons 8 Edgelay)))) (foreach en (mapcar (function cadr) (ssnamex ssl)) (setq edges (cons (list (butlast (vlax-curve-getstartpoint en)) (butlast (vlax-curve-getendpoint en))) edges)) ) ) (setq startp (butlast (getpoint "\nPick Start Point: ")) ; Startpoint - reduced to 2D ; endp (butlast (getpoint "\nPick End Point: ")) ; Endpoint - reduced to 2D ; openlst (list (list startp '(0 0) 0.0 (distance startp endp))) ; Add starting node to openlst ; ) (vla-startundomark acdoc) (setq ti (getvar 'MILLISECS)) (while (and openlst (not found)) (setq node (car openlst)) (if (equal (car node) endp 1e-4) (setq found T closelst (cons node closelst)) (setq closelst (cons node closelst) openlst (upd_openlst edges node endp (cdr openlst) closelst) ) ) ) (if found (mk_lwp (get_path closelst)) (alert "No path was found") ) (princ (strcat "\nExecution time:" (itoa (- (getvar 'MILLISECS) ti)) " milliseconds.")) (*error* nil) ) ;; ; ;; upd_openlst ; ;; ; ;; Each node of the openlst is passed to this sub and we scan the edges list ; ;; to find the corresponding edges. Then both points of the edges are tested ; ;; for equality to the nodes. The fixed cost (distance) is updated and so is ; ;; the estimated total distance. Updates are first put in a temporary node. ; ;; ; ;; We then proceed to test if the temp variable is already in the closelst ; ;; and proceed to the next edge. ; ;; ; ;; If temp is true and temp is not in closelst we go to the recursive sub ; ;; in_openlst which adjust the values and return the updated openlst : ;; ; ;; Upon return we sort the openlst on smallest estimated distance ; ;; and return the openlst to the main routine ; ;; ; (defun upd_openlst (edges node endp openlst closelst / pt fcost p1 p2 d temp) (setq pt (car node) fcost (caddr node)) (while edges (setq p1 (caar edges) p2 (cadar edges) edges (cdr edges) d (distance p1 p2) temp nil) ;Testing both points of an edge and building a temporary node ; (cond ((equal pt p1 1e-4) (setq temp (list p2 p1 (+ fcost d) (+ fcost d (distance p2 endp))))) ((equal pt p2 1e-4) (setq temp (list p1 p2 (+ fcost d) (+ fcost d (distance p1 endp))))) ) (if (and temp (not (memberfuzz (car temp) closelst))) (setq openlst (in_openlst temp openlst)) ) ) ; Keep openlist sorted on smallest Estimated Total Cost ; (print (vl-sort openlst (function (lambda(a b)(< (cadddr a) (cadddr b))))) ) ) ;in_lst Replaced by memberfuzz ; ;(defun in_lst (pt lst) ; (cond ; ((not lst) nil) ; ((equal pt (caar lst) 1e-4) lst) ; (T (in_lst pt (cdr lst))) ; ) ;) ; returns a new openlst with a double exchanged if cost is lower ; ;; ; (defun in_openlst (node lst) (cond ((not lst) (list node)) ((equal (car node) (caar lst) 1e-4) (if (< (cadddr node) (cadddr (car lst))) (cons node (cdr lst)) lst ) ) (T (cons (car lst) (in_openlst node (cdr lst)))) ) ) (defun in_openlst2 (node lst / s c) (setq s (splitat (caar node) lst) c (cadddr node)) (cond ((not lst) (list node)) ((not (car s)) (cons node (cadr s))) ((not (cadr s)) (cons node (car s))) (T (if (< (cadddr node) (cadddr (cadr s))) (append (car s) (cons node (cdr s))) lst )) ;(T (c ns node lst)) ) ) ;; ; ;; listpol2D by ymg (Simplified a Routine by Gile Chanteau ; ;; ; ;; Parameter: en, Entity Name or Object Name of Any Type of Polyline ; ;; ; ;; Returns: List of Points in 2D WCS ; ;; ; ;; Notes: Requires butlast function for 2d points. ; ;; ; (defun listpol2d (en / i lst) (repeat (setq i (fix (1+ (vlax-curve-getEndParam en)))) (setq lst (cons (butlast (vlax-curve-getPointAtParam en (setq i (1- i)))) lst)) ) ) ;; ; ;; mk_edge ; ;; ; ;; From a list of consecutives points as supplied by listpol2D, ; ;; Returns a list of edges (((x1 y1)(x2 y2)) ((x2 y2)(x3 y3))...) ; ;; ; (defun mk_edge (lst) (mapcar (function (lambda (a b) (list a b ))) lst (cdr lst)) ) ;; ; ;; butlast ; ;; ; ;; Returns a list without the last item ; ;; Used here mainly to change points to 2D ; ;; ; (defun butlast (lst) (reverse (cdr (reverse lst)))) ;; ; ;; get_path ; ;; ; ;; Returns The list of points of shortest path found from closelst. ; ;; ; (defun get_path (lst / path) (setq path (list (caar lst)) prev (cadar lst) lst (cdr lst)) (while (setq lst (memberfuzz prev lst)) (setq prev (cadar lst) path (cons (caar lst) path) ) ) path ) ;; ; ;; memberfuzz by Gile Chanteau ; ;; ; ;; Modified to work with nodes list ; ;; ; (defun memberfuzz (p lst) (while (and lst (not (equal p (caar lst) 1e-4))) (setq lst (cdr lst)) ) lst ) (defun splitat (p lst / tr) (while (and lst (not (equal p (caar lst) 1e-4))) (setq tr (cons (car lst) tr) lst (cdr lst)) ) (list (reverse tr) lst) ) (defun truncfuzz (p lst) (if (and lst (not (equal p (caar lst) 1e-4))) (cons (car lst) (truncfuzz p (cdr lst))) ) ) (defun posfuzz (p lst) (- (length lst) (length (memberfuzz p lst))) ) (defun rotleft (lst) (append (cdr lst) (list (car lst)))) (defun rotright (lst) (cons (last lst) (butlast lst))) ;; ; ;; mk_lwp ; ;; ; ;; Draw an lwpolyline given a point list ; ;; ; ;; Will be drawn on layer with color and lineweight defined by Variables ; ;; at beginnung of program. ; ;; ; (defun mk_lwp (pl) (entmakex (append (list (cons 0 "LWPOLYLINE") (cons 100 "AcDbEntity") (cons 100 "AcDbPolyline") (cons 8 Pathlay) (cons 62 Pathcol) (cons 90 (length pl)) (cons 70 0) (cons 370 Pathlwt) ) (mapcar (function (lambda (a) (cons 10 a))) pl) ) ) ) ;; Error Handler by Elpanov Evgenyi ; (defun set_errhandler (l) (setq varl (mapcar (function (lambda (a) (list 'setvar a (getvar a)))) l)) ) (defun *error* (msg) (mapcar 'eval varl) (if (and msg (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*"))) (princ (strcat "\nError: " msg)) ) (vla-endundomark acdoc) (princ) ) (princ "A* to start") Astar rev3.lsp astar test.dwg1 point
-
I’ve been experimenting with @lrm's tool to generate segment-by-segment bisectors. In many cases I was able to chain them together without any issues, and the equidistance was achieved. But in the more curved areas, the bisectors produced by each pair of segments lead to results that make it impossible to connect them without losing that equidistance. So I must apologize for my excessive optimism I guess the goal can only be to achieve true equidistance wherever it’s geometrically possible, and where it isn’t, to get the smallest deviation we can. In the attached images you can see in red the result of using Irm’s tool segment by segment and manually joining the endpoints. The result is an equidistant centerline along most of the path. But as you can see in the area where the margins widen significantly, the geometry of the axis becomes very fuzzy. Alongside my manual work with Irm’s tool, you can also see the output from commands "CPL" by @GP_ and "cl" by @dexus/@marko_ribar. In fact, "cl" produces something very close to a true equidistant centerline, although it can be a bit irregular at times. And I suppose the issue with redundant points can be solved easily. So it seems that the solution by Dexus/Ribar is the best one so far.1 point
