BaneB Posted August 4 Posted August 4 I need a lisp to divide curves (arc, ellipse, polyline...) by given chord height. For example, more points should be created on a larger curve then on a smaller curve. Thanks in advance. Quote
SLW210 Posted August 4 Posted August 4 I have moved your thread to the AutoLISP, Visual LISP & DCL Forum. Please post in the most appropriate forum. Quote
BIGAL Posted August 4 Posted August 4 (edited) Its a geometry thing so rather than us work out the formula why don't you have a go and then we can convert it to a lisp. Need to know what you call a large radius. Edited August 4 by BIGAL Quote
lamensterms Posted August 7 Posted August 7 (edited) Do you mean chord length or versine? Chord is AB, versine is CD I was intrigued by this requested - and wanted to test ChatGPTs LISP and math prowess (not sure if allowed - and apologies if this is an insult to the resident LISP gurus!). Results might be useful, but I was impressed it was able to get this far. It took 9 attempts to arrive at this code 2 routines below: DABV1 - divides an ARC into lengths according to specified versine, with a 'remainder' arc DBAV2 - creates equal arc lengths up to maximum of specified versine (defun c:DABV1 ( / arcEntity arcData center radius startAngle endAngle versine chordLength angleIncrement totalAngle numSegments newArcs i angle1 angle2) ;; Function to calculate the arc sine (asin) value (defun asin (x) (atan (/ x (sqrt (- 1 (* x x)))))) ;; Function to calculate the chord length for a given versine and radius (defun chord-for-versine (v r) (* 2 (sqrt (- (* r r) (* (- r v) (- r v)))))) ;; Function to calculate the angle increment for a given chord length and radius (defun angle-for-chord-length (c r) (* 2 (asin (/ (/ c 2) r)))) ;; Get the arc entity from the user (setq arcEntity (entsel "\nSelect an arc: ")) (if (and arcEntity (setq arcEntity (car arcEntity))) (progn (setq arcData (entget arcEntity)) ;; Check if the selected entity is an arc (if (eq (cdr (assoc 0 arcData)) "ARC") (progn ;; Get the arc properties (setq center (cdr (assoc 10 arcData))) (setq radius (cdr (assoc 40 arcData))) (setq startAngle (cdr (assoc 50 arcData))) (setq endAngle (cdr (assoc 51 arcData))) ;; Prompt the user for the versine length (setq versine (getreal "\nEnter the versine length: ")) ;; Ensure versine and radius are positive and radius is non-zero (if (and versine (> versine 0) radius (> radius 0)) (progn ;; Calculate the chord length for the given versine length (setq chordLength (chord-for-versine versine radius)) ;; Calculate the angle increment for the given chord length (setq angleIncrement (angle-for-chord-length chordLength radius)) ;; Calculate the total angle of the arc (setq totalAngle (- endAngle startAngle)) ;; Calculate the number of segments based on the total angle and the angle increment (setq numSegments (fix (/ totalAngle angleIncrement))) ;; Create new arcs (setq newArcs nil) (setq angle1 startAngle) (repeat numSegments (setq angle2 (+ angle1 angleIncrement)) (setq newArcs (cons (entmakex (list (cons 0 "ARC") (cons 10 center) (cons 40 radius) (cons 50 angle1) (cons 51 angle2))) newArcs)) (setq angle1 angle2) ) ;; If there's a remaining segment, add it (if (< angle1 endAngle) (setq newArcs (cons (entmakex (list (cons 0 "ARC") (cons 10 center) (cons 40 radius) (cons 50 angle1) (cons 51 endAngle))) newArcs)) ) ;; Display the new arcs (foreach arc newArcs (entdraw arc)) ) (princ "\nInvalid versine length or radius.") ) ) (princ "\nSelected entity is not an arc.") ) ) (princ "\nNo arc selected.") ) (princ) ) (defun ceiling (x) (if (= x (fix x)) (fix x) (+ (fix x) 1))) (defun c:DABV2 ( / arcEntity arcData center radius startAngle endAngle versine chordLength maxAngleIncrement totalAngle numSegments actualAngleIncrement newArcs i angle1 angle2) ;; Function to calculate the arc sine (asin) value (defun asin (x) (atan (/ x (sqrt (- 1 (* x x)))))) ;; Function to calculate the chord length for a given versine and radius (defun chord-for-versine (v r) (* 2 (sqrt (- (* r r) (* (- r v) (- r v)))))) ;; Function to calculate the angle increment for a given chord length and radius (defun angle-for-chord-length (c r) (* 2 (asin (/ (/ c 2) r)))) ;; Get the arc entity from the user (setq arcEntity (entsel "\nSelect an arc: ")) (if (and arcEntity (setq arcEntity (car arcEntity))) (progn (setq arcData (entget arcEntity)) ;; Check if the selected entity is an arc (if (eq (cdr (assoc 0 arcData)) "ARC") (progn ;; Get the arc properties (setq center (cdr (assoc 10 arcData))) (setq radius (cdr (assoc 40 arcData))) (setq startAngle (cdr (assoc 50 arcData))) (setq endAngle (cdr (assoc 51 arcData))) ;; Prompt the user for the versine length (setq versine (getreal "\nEnter the versine length: ")) ;; Ensure versine and radius are positive and radius is non-zero (if (and versine (> versine 0) radius (> radius 0)) (progn ;; Calculate the chord length for the given versine length (setq chordLength (chord-for-versine versine radius)) ;; Calculate the maximum angle increment for the given chord length (setq maxAngleIncrement (angle-for-chord-length chordLength radius)) ;; Calculate the total angle of the arc (setq totalAngle (- endAngle startAngle)) ;; Calculate the number of segments required, rounding up to ensure the versine is not exceeded (setq numSegments (ceiling (/ totalAngle maxAngleIncrement))) ;; Calculate the actual angle increment to evenly divide the arc into `numSegments` (setq actualAngleIncrement (/ totalAngle numSegments)) ;; Create new arcs (setq newArcs nil) (setq angle1 startAngle) (repeat numSegments (setq angle2 (+ angle1 actualAngleIncrement)) (setq newArcs (cons (entmakex (list (cons 0 "ARC") (cons 10 center) (cons 40 radius) (cons 50 angle1) (cons 51 angle2))) newArcs)) (setq angle1 angle2) ) ;; Display the new arcs (foreach arc newArcs (entdraw arc)) ) (princ "\nInvalid versine length or radius.") ) ) (princ "\nSelected entity is not an arc.") ) ) (princ "\nNo arc selected.") ) (princ) ) Edited August 7 by lamensterms deleted surplus attachment 1 Quote
BIGAL Posted August 7 Posted August 7 You could look at something like this that asks for number of chords, you would use say radius values to set how many. In Civil works there are no curved breaklines so a work around is to ask for the max versine value and work back from that. May be the way to go with rather than looking at a radius. ; converts an arc to a series of straights ; By Alan H 2012 ; (vl-load-com) (defun C:arc2chords ( / ss ncrd oldsnap ent endpt obj totlen arclen chrdpt num newpt ang cenpt) (setq oldsnap (getvar "osmode")) (if (= ncrd nil) (setq ncrd (getint "\nEnter number of chords: "))) (setvar 'osmode 512) (while (setq pt (getpoint "Pick Arc or Circle")) (setq ss (ssget pt (list (cons 0 "Arc,Circle")))) (setq obj (vlax-ename->vla-object (ssname ss 0 ))) (if (= "AcDbArc" (vla-get-objectname obj)) (progn (setq endpt (vlax-curve-getEndPoint obj)) (setq totlen (vla-get-ArcLength obj)) (setq arclen (/ totlen ncrd)) (setq chrdpt (vlax-curve-getStartPoint obj)) (setq num 1) (command "_Pline" ) (while (= (getvar "cmdactive") 1 ) (command chrdpt) (repeat ncrd (command (vlax-curve-getPointatDist obj (* arclen num))) (setq num (+ num 1)) ) (command endpt) (command "") ) ) ) (if (= "AcDbCircle" (vla-get-objectname obj)) (progn (setq rad (vla-get-radius obj)) (setq cenpt (vlax-safearray->list (vlax-variant-value (vla-get-center obj)))) (setq totlen (* pi (* 2.0 rad))) (setq ang (/ (* pi 2.) ncrd)) (setq chrdpt (polar cenpt 0.0 rad)) (setq num 1.0) (command "_Pline" ) (while (= (getvar "cmdactive") 1 ) (command chrdpt) (repeat ncrd (command (polar cenpt (* num ang) rad)) (setq num (1+ num)) ) (command "c") ) ) ) (setvar "osmode" oldsnap) ) (princ) ) (c:arc2chords) PS look at the date created. 1 Quote
lamensterms Posted August 8 Posted August 8 Nice BigAl. I frequently use a similar routine for those types of exercises - Lee Mac's SEGS I use it instead of the native DIVIDE 2012!? 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.