Jump to content

Divide curve (create points) by given chord height


BaneB

Recommended Posts

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.

Link to comment
Share on other sites

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 by BIGAL
Link to comment
Share on other sites

Do you mean chord length or versine?

 

Chord is AB, versine is CD

 

image.png.6a05ca4d9af45cfdfd26dad2b9ace993.png

 

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

 

image.thumb.png.63b3399cc4a84cf21e85b668e0ab9ce6.png

 

(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 by lamensterms
deleted surplus attachment
  • Like 1
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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!?

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...