Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/03/2025 in all areas

  1. As for the code from my first attempt, I suppose the least I should do for any “child of mine” is to make sure it can have a functional life, no matter how cross-eyed it was born: you never abandon a child. So here I leave a new version of “GLAVCVS’ cross-eyed child”, fresh out of the hospital. ;| G L A V C V S C R O S S - E Y E D C H I L D - o - ************************* G L A V C V S ************************* *************************** F E C I T ***************************|; (defun c:creAxis (/ e e1 e2 l i? l1 l2 lr p p0 p1 p2 px pm abis lii pmi pmf pi1 pi2 pf1 pf2 pc1 pc2 li1 o dameInters+Prox ordena decide sustituye damePuntos) (defun dameInters+Prox (p0 a lp / p1 px pt1 pt2 dmin d pf) (setq pt1 (polar p0 a 1e8) pt2 (polar p0 (+ a PI) 1e8)) (foreach p lp (if p1 (if (setq px (inters pt1 pt2 p1 p)) (if dmin (if (< (setq d (distance px p0)) dmin) (setq dmin d pf px)) (setq dmin (distance px p0) pf px)) ) ) (setq p1 p) ) pf ) (defun ordena (po px pm / p0 lr) (foreach p lii (if (and p0 (inters po px p0 p)) (setq lr (append lr (list pm))) ) (setq p0 p lr (append lr (list p))) ) ) (if (and (setq e1 (car (entsel "\nSelect FIRST LWPOLYLINE..."))) (= (cdr (assoc 0 (setq l1 (entget e1)))) "LWPOLYLINE") (not (redraw e1 3))) (if (and (setq e2 (car (entsel "\nSelect SECOND LWPOLYLINE..."))) (= (cdr (assoc 0 (setq l2 (entget e2)))) "LWPOLYLINE") (not (redraw e2 3))) (progn (setq lp1 (reverse (foreach l l1 (if (= (car l) 10) (setq lr (cons (cdr l) lr)) lr))) lr nil lp2 (reverse (foreach l l2 (if (= (car l) 10) (setq lr (cons (cdr l) lr)) lr))) lr nil ) (cond ((= (rem (cdr (assoc 70 l1)) 2) 1) (setq lp1 (append lp1 (list (car lp1) (cadr lp1) (caddr lp1)))) ) ((equal (car lp1) (last lp1)) (setq lp1 (append lp1 (list (cadr lp1) (caddr lp1)))) ) (T (setq pmi (mapcar '(lambda (a b) (/ (+ a b) 2.0)) (car lp1) (setq pc1 (vlax-curve-getClosestPointTo e2 (car lp1)))) pmf (mapcar '(lambda (a b) (/ (+ a b) 2.0)) (last lp1) (setq pc2 (vlax-curve-getClosestPointTo e2 (last lp1)))) ) ) ) (cond ((= (rem (cdr (assoc 70 l2)) 2) 1) (if pmi (progn (foreach p (append lp2 (list (car lp2))) (if (or (equal p pmi 1e-4) (equal p pmf 1e-4)) (setq l (if l (not (setq lr (append l (list p)))) (list (list p)))) (if l (setq l (append l (list p)))) ) ) (setq lp2 lr lr nil l nil) ) (setq lp2 (append lp2 (list (car lp2) (cadr lp2)))) ) ) ((equal (car lp2) (last lp2)) (if pc1 (progn (foreach p lp2 (if (or (equal p pc1 1e-4) (equal p pc2 1e-4)) (setq l (if l (not (setq lr (append l (list p)))) (list (list p)))) (if l (setq l (append l (list p)))) ) ) (setq lp2 lr lr nil l nil) ) (setq lp2 (append lp2 (list (cadr lp2)))) ) ) ) (redraw e1 4) (redraw e2 4) (foreach lp (list lp1 lp2) (foreach l lp (if p1 (if p2 (setq abis (+ (/ (+ (angle p1 p2) (angle p2 l)) 2) (/ PI 2.)) px (dameInters+Prox p2 abis (if o lp1 lp2)) lr nil pm (if px (mapcar '(lambda (a b) (/ (+ a b) 2.0)) p2 px)) lii (if o (if pm (ordena p2 px pm) lii) (if px (append lii (list pm)) lii)) p1 p2 p2 l ) (setq p2 l) ) (setq p1 l) ) ) (if pmi (setq lii (append (list pmi) lii (list pmf)))) (setq p1 nil p2 nil lr nil o T) ) ) ) ) (entmake (append '((0 . "LWPOLYLINE") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbPolyline") (70 . 0) (60 . 0)) (list (cons 90 (length lii))) (mapcar '(lambda (a) (cons 10 a)) lii))) (princ) )
    4 points
  2. [code edited 11/3/2025] I have enjoyed the discussion of this thread. As I gave the task more thought and anaysis it became more clear that the task was not simple. As it appears that there is still no satisfacory solution I thought I would offer the following. The first goal for me was to create a function that would create a midline between two non parallel lines. The mid-lines extents should be a function of the given line segments. This function could then be used in a program that would step through the line segments of one of the polylines and search the other polyline for relevant segments. The function "midline" accepts four points. The first two points, A1 and A2, are the ends of one line sement while the thrid and fourth points, B1 and B2, are the ends of an opposing ilne segments. The diagram below details the variables in the function. The program uses vectors as I prefer them over angles which present, for me, a variety of problems. uA = unit vector in the diection from A1 to A2 uB = unit vector in the direction from B1 to B2 uBisector = unit vector in the direction of the angle bisector of uA and UB The ends of the two lines are projected onto the bisecting line defining 4 points, A1M, A2M, B1M, B2M. I debated which of the points to output for the line to be drawn. I first used the closest and furthest points from the intersecttion point ABIntr but I found it more helpful to use the two intermediate points (A1M and A2M in the example above). Here's an example of the results after manually steppng alone the polyline. Looking at the area circled in red we find: To fill the gap we need a curve that starts with a radius of 0.1514 and ends with a radius of 0.1693. This can be done with a spline or you may find it acceptable to extend the two lines to the point of intersection. The best way to create the spline is to use the Control Vertex Method and use the two endpoints and the imaginary point of intersecton for the middle CV. This ensures tangency to the two lines. As can be seen below the distance to a random point along the spline (red) agree! Run the program "test" and specify the end points of a line segment on one of the polylines, then the endpoints on a line segment on the opposing polyline. I have found the results very accurate and although it may not be used for creating the complete "hybrid " polyline it is helpful in finding the correct line for a specific segment. ;;---------------------------------------------------------------------------- ;; Determines the endpoints of a line the is midway between two lines defined by their end points. ; Input: 4 points, the ends of the first line followed by the ens of the second line ; Output: a list containing the two point of the midline if there's a solution and nil if no solution ; L. Minardi 10/31/2025 - Revised 11/3/2025 (defun midLine (a1 a2 b1 b2 / ua ub p vp d s a1m a2m b1m b2m d1 d2 d3 d4 slist a1p a2p b1p b2p m1 m2 mmid mp) (setq ua (unitVecAB a1 a2) ub (unitVecAB b1 b2) ) (if (< (dot ua ub) 0.0) (setq ub (mapcar '* ub '(-1 -1 -1))) ) (if (> (abs (dot ua ub)) 0.9999) ; are lines parallel? (progn ; lines are parallel (setq p (mapcar '/ (mapcar '+ a1 b1) '(2 2 2)) ; point on midline vp (list (- (cadr ua)) (car ua) 0.0) ; vector perpendicular to ua d (/ (dot (mapcar '- b1 a1) vp) 2.0) ; distance to midline s (dot (mapcar '- a1 p) ua) a1m (mapcar '+ p (mapcar '* ua (list s s s))) s (dot (mapcar '- a2 p) ua) a2m (mapcar '+ p (mapcar '* ua (list s s s))) s (dot (mapcar '- b1 p) ua) b1m (mapcar '+ p (mapcar '* ua (list s s s))) s (dot (mapcar '- b2 p) ua) b2m (mapcar '+ p (mapcar '* ua (list s s s))) d1 0.0 d2 (dot ua (mapcar '- a2m a1m)) d3 (dot ua (mapcar '- b1m a1m)) d4 (dot ua (mapcar '- b2m a1m)) ) (setq slist ; sorted list of distances (vl-sort (list (list a1m d1) (list a2m d2) (list b1m d3) (list b2m d4)) (function (lambda (e1 e2)(< (cadr e1) (cadr e2)))))) ; use the middle two mid point from the line (setq m1 (car (nth 1 slist)) m2 (car (nth 2 slist)) ) (setq mmid (mapcar '/ (mapcar '+ m1 m2) '(2 2 2))) (setq mp (* (dot (mapcar '- a1m mmid) (mapcar '- a2m mmid)))) (if (<= mp 0) (setq theLine (list m1 m2)) (setq theline nil) ) ;;;;; ) ) ; end lines parallel (progn ; lines are not parallel (setq ABIntr (inters A1 A2 B1 B2 nil)) (setq p (mapcar '+ ABIntr (mapcar '/ (mapcar '+ ua ub) '(2 2 2))) ;(setq p (mapcar '+ ABIntr (mapcar '/ (mapcar '+ a1 b1) '(2 2 2))) uBisector (unitVecAB ABIntr p) vp (list (- (cadr ua)) (car ua) 0.0) A1p (mapcar '+ A1 vp) a1m (inters A1 A1P ABIntr p nil) A2p (mapcar '+ A2 vp) a2m (inters A2 A2P ABIntr p nil) vp (list (- (cadr ub)) (car ub) 0.0) B1p (mapcar '+ B1 vp) B1m (inters B1 B1P ABIntr p nil) B2p (mapcar '+ B2 vp) B2m (inters B2 B2P ABIntr p nil) d1 (distance ABIntr a1m) d2 (distance ABIntr a2m) d3 (distance ABIntr b1m) d4 (distance ABIntr b2m) ) (setq slist (vl-sort (list (list a1m d1) (list a2m d2) (list b1m d3) (list b2m d4)) (function (lambda (e1 e2) (< (cadr e1) (cadr e2))))) ) (setq m1 (car (nth 1 slist)) m2 (car (nth 2 slist)) ) (setq mmid (mapcar '/ (mapcar '+ m1 m2) '(2 2 2))) (setq mp (* (dot (mapcar '- a1m mmid) (mapcar '- a2m mmid)))) (if (<= mp 0) (setq theLine (list m1 m2)) (setq theline nil) ) ) ; end lines not parallel ) ; end if ) ; test function (defun c:test ( / a1 a2 b1 b2 mline ) (setq a1 (getpoint "\nEnter start point of first line: ") a2 (getpoint a1 "\nEnter end point of first line: ") b1 (getpoint "\nEnter start point of second line: ") b2 (getpoint b1 "\nEnter end point of second line: ") mline (midline a1 a2 b1 b2) ) (if mline (command "_line" "_non" (car mline) "_non" (cadr mline) "") (princ "\nNo Solution!") ) (princ) ) ; unit vector from point A to point B (defun unitVecAB (A B / x) (setq x (distance A B) x (mapcar '/ (mapcar '- B A) (list x x x)) ) ) ; dot product of vectors A and B (defun dot (A B / x) (setq x (mapcar '* A B)) (setq x (+ (nth 0 x) (nth 1 x) (nth 2 x))) );end of dot mid -poly.06.lsp
    4 points
  3. I also think this thread has been stimulating. The final result should be useful for other users in the future. Regarding your approach, I agree; it's the best way to achieve an axis with perfectly centered segments. All that remains is to write the code that can do all of that without Express Tools.
    2 points
  4. Another version just drag over the plines left and right. https://www.cadtutor.net/forum/topic/98797-looking-for-a-lisp-to-evenly-space-polylines-from-their-end-points/ ; paralelle lines change ; offset a pline by an amount ; by AlanH Nov 2025 (defun c:wow ( / co-ord len1 len2 lst off off2 pt1 pt2 pts) ; Checking if pline is CW or CCW and set to CCW ; Orignal idea by Kent Cooper, 1 August 2018 Offsetinorout.lsp ; Modified By Alan H July 2020 (defun AH:chkcwccw (ent / area1 area2 dist lst obj objnew pointmax pointmin) (setq obj (vlax-ename->vla-object ent)) (setq lst (vlax-get obj 'coordinates)) (vla-GetBoundingBox obj 'minpoint 'maxpoint) (setq pointmin (vlax-safearray->list minpoint)) (setq pointmax (vlax-safearray->list maxpoint)) (setq dist (/ (distance pointmin pointmax) 20.0)) (vla-offset obj dist) (setq objnew (vlax-ename->vla-object (entlast))) (setq area1 (vlax-get objnew 'Area)) (vla-delete objnew) (vla-offset obj (- dist)) (setq objnew (vlax-ename->vla-object (entlast))) (setq area2 (vlax-get objnew 'Area)) (vla-delete objnew) (if (> area1 area2) (progn (command "pedit" ent "R" "") (setq lst (vlax-get obj 'coordinates)) ) ) (princ) ) (defun replace-nth (lst n newVal) (cond ((null lst) nil) ((= n 0) (cons newVal (cdr lst))) (T (cons (car lst) (replace-nth (cdr lst) (1- n) newVal)))) ) (setq oldsnap (getvar 'osmode)) (setvar 'osmode 0) (setq off (getreal "\nEnter offset value ")) (while (setq pt1 (getpoint "\nPick 1st point outside ")) (setq pt2 (getpoint pt1 "\nPick 2nd point inward ")) (setq off2 (/ off 2.0)) (setq pts (list pt1 pt2)) (setq ss (ssget "F" pts '((0 . "LWPOLYLINE")))) (repeat (setq x (sslength ss)) (setq plent (ssname ss (setq x (1- x)))) (AH:chkcwccw plent) (setq len1 (distance (list (nth 0 lst)(nth 1 lst)) (list (nth 2 lst)(nth 3 lst)))) (setq len2 (distance (list (nth 4 lst)(nth 5 lst))(list (nth 6 lst)(nth 7 lst)))) (if (> len1 len2) (progn (setq lst (replace-nth lst 0 (+ (nth 0 lst) off2))) (setq lst (replace-nth lst 2 (+ (nth 2 lst) off2))) (setq off2 (+ off2 off)) ) (progn (setq lst (replace-nth lst 6 (- (nth 6 lst) off2))) (setq lst (replace-nth lst 4 (- (nth 4 lst) off2))) (setq off2 (+ off2 off)) ) ) (vlax-put obj 'coordinates lst) ) ) (setvar 'osmode oldsnap) (princ) ) (c:wow)
    1 point
  5. Edited Not quite there yet, will draw points at the mid points between each coordinate in the polylines and the closest point in the other. Draws a poly line connecting most of them... but not quite... Something odd if you select the polylines in the wrong order. Results are similar to what others have. No account taken for arcs yet (defun c:PolyMD ( / acount MyPoly1 MypolyEnt1 MyPolyVert1 MyPoly2 MypolyEnt2 MyPolyVert2 pt pt1 pt2 PtList1 PtList2 pnt NewPoly NewPolyEnt) ;;; Sub functions ;;;;;; ;;https://www.cadtutor.net/forum/topic/87445-help-add-vertex-to-polyline/ (defun add_vtx (obj add_pt ent_name / sw ew nw bulg) (vla-GetWidth obj (fix add_pt) 'sw 'ew) (vla-addVertex obj (1+ (fix add_pt)) (vlax-make-variant (vlax-safearray-fill (vlax-make-safearray vlax-vbdouble (cons 0 1)) (list (car (trans (vlax-curve-getpointatparam obj add_pt) 0 ent_name)) (cadr (trans (vlax-curve-getpointatparam obj add_pt) 0 ent_name)) ) ) ) ) (setq nw (* (/ (- ew sw) (- (vlax-curve-getdistatparam obj (1+ (fix add_pt))) (vlax-curve-getdistatparam obj (fix add_pt))) ) (- (vlax-curve-getdistatparam obj add_pt) (vlax-curve-getdistatparam obj (fix add_pt))) ) bulg (atan (vla-GetBulge obj (fix add_pt))) ) (vla-SetBulge obj (fix add_pt) (/ (sin (* 4 bulg (- add_pt (fix add_pt)) 0.25)) (cos (* 4 bulg (- add_pt (fix add_pt)) 0.25)) ) ) (vla-SetBulge obj (1+ (fix add_pt)) (/ (sin (* 4 bulg (- (1+ (fix add_pt)) add_pt) 0.25)) (cos (* 4 bulg (- (1+ (fix add_pt)) add_pt) 0.25)) ) ) (vla-SetWidth obj (fix add_pt) sw (+ nw sw) ) (vla-SetWidth obj (1+ (fix add_pt)) (+ nw sw) ew ) (vla-update obj) ) (defun add_vtx@point (ename lst_pt / n ename obj dxf_10 pt_brk l_tst) (setq obj (vlax-ename->vla-object ename)) (setq dxf_10 (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ename)))) (foreach el (mapcar '(lambda (x) (trans x 0 ename)) lst_pt) (setq pt_brk (trans (vlax-curve-getClosestPointTo ename (trans el ename 0) nil) 0 ename)) (setq l_tst (vl-member-if '(lambda (x) (and (equal (car x) (car pt_brk) 1E-08) (equal (cadr x) (cadr pt_brk) 1E-08))) dxf_10)) (if (and (equal pt_brk el 1E-08) (not (eq (length l_tst) 1)) (not (eq (length l_tst) (length dxf_10))) ) (progn (setq lst_brk (cons pt_brk lst_brk)) (if (zerop (length l_tst)) (add_vtx obj (vlax-curve-getparamatpoint ename (trans pt_brk ename 0)) ename) ) ) ) ) ) (defun mAssoc ( key lst / result ) (foreach x lst (if (= key (car x)) (setq result (cons (cdr x) result)) ) ) (reverse result) ) ; end Massoc (defun midpt (p1 p2) (polar p1 (angle p1 p2) (/ (distance p1 p2) 2.) ) ) (defun LM:Unique ( l ) (if l (cons (car l) (LM:Unique (vl-remove (car l) (cdr l))))) ) (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 MakePoly (PtLst PolyClose / ) (princ "Close: ")(princ PolyClose) (entmakex (append (list (cons 0 "LWPOLYLINE") (cons 100 "AcDbEntity") (cons 100 "AcDbPolyline") (cons 90 (length PtLst)) ;; (cons 70 PolyClose) ) (mapcar (function (lambda (p) (cons 10 p))) PtLst) )) ) (defun MakePoint ( pt / ) (entmakex (list '(0 . "POINT") '(100 . "AcDbEntity") '(100 . "AcDbPoint") (cons 10 pt) )) ) (defun MakeLine (pt1 pt2 / ) (entmakex (list '(0 . "LINE") '(100 . "AcDbEntity") '(100 . "AcDbLine") (cons 10 pt1) (cons 11 pt2) )) ) ;;;;;;; end sub functions ;;;;;;; (setq MyPoly1 (car (entsel "\nSelect Outer Polyline: "))) (setq MyPoly1Ent (entget MyPoly1)) (setq MyPoly1Vert (mAssoc 10 MyPoly1Ent)) (setq MyPoly2 (car (entsel "\nSelect Inner Polyline 2: "))) (setq MyPoly2Ent (entget MyPoly2)) (setq MyPoly2Vert (mAssoc 10 MyPoly2Ent)) (foreach pt MyPoly1Vert (setq pt2 (vlax-curve-getclosestpointto MyPoly2 pt)) (setq PtList1 (cons (midpt pt pt2) PtList1)) ) ; end foreach (setq NewPoly (MakePoly PtList1 (cdr (assoc 70 MyPoly1Ent)))) (setq NewPolyEnt (entget NewPoly)) (foreach pt MyPoly2Vert (setq pt1 (vlax-curve-getclosestpointto MyPoly1 pt)) (setq NewLine (makeline pt pt1)) (setq PtList2 (cons (midpt pt pt1) PtList2)) (setq pnt (car (LM:intersections (vlax-ename->vla-object NewLine) (vlax-ename->vla-object NewPoly) acextendnone))) (setq pnt (list (car pnt) (cadr pnt))) (add_vtx@point NewPoly (list pnt)) (setq NewPolyEnt (entget NewPoly)) (setq NewPolyEnt (subst (cons 10 (midpt pt pt1) ) (cons 10 pnt) NewPolyEnt )) (entmod NewPolyEnt) ;; (entupd NewPoly) (command "erase" NewLine "") ) ; end foreach (foreach pt PtList1 (Makepoint pt) ) (foreach pt PtList2 (Makepoint pt) ) ;;Work out if midpoints outside of exterior polyline (in case of complicated shapes) ;;Work out polyline bulges ;;If closed poly, add end vertex (princ) )
    1 point
  6. 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 point
×
×
  • Create New...