# LISP to Math formula / Ruby code

**URL:** <https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667>\
**Category:** Ruby API\
**Tags:** sketchup, advice, autocad\
**Created:** [August 14, 2021, 4:50am UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667 "2021-08-14T04:50:44Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![marcosyu](https://avatars.discourse-cdn.com/v4/letter/m/53a042/32.png) [@marcosyu](https://forums.sketchup.com/u/marcosyu)\
**Post date:** [August 14, 2021, 4:50am UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/1 "2021-08-14T04:50:44Z")

</div>

> **[Bulge Conversion Functions | Lee Mac Programming](http://www.lee-mac.com/bulgeconversion.html#arcbulge)**
>
> A set of functions to convert between quantities used to define an arc entity and those used to define a polyline arc segment

Hi there, I’m a ruby developer and starting to be sketchup developer. I was looking for some formula for my bulge calculation and I stumble upon this LISP formula that could help me but unfortunately I don’t have any LISP experience and couldn’t understand it. Could someone help me translate this?

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [August 14, 2021, 12:45pm UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/2 "2021-08-14T12:45:48Z")

</div>

My attempt at translating this LISP function is [below in post 5](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/5) …

* * *

Let us say that this topic would be a follow on from this one …

- [LWPOLYLINE creating arcs from vertices / edges](https://forums.sketchup.com/t/lwpolyline-creating-arcs-from-vertices-edges/139570)

---

<div class="post-metadata">

**Author:** ![marcosyu](https://avatars.discourse-cdn.com/v4/letter/m/53a042/32.png) [@marcosyu](https://forums.sketchup.com/u/marcosyu)\
**Post date:** [August 14, 2021, 1:23pm UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/3 "2021-08-14T13:23:00Z")

</div>

Yes, thanks it actually does apparently the formula that ive used previously returns unexpected behavior (arcs are rotating in different direction) but the bulge value is correct

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [August 14, 2021, 1:38pm UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/4 "2021-08-14T13:38:51Z")

</div>

> [@marcosyu](#):
>
> arcs are rotating in different direction

Did you take into account the direction that the ArcCurve’s [`normal`](https://ruby.sketchup.com/Sketchup/ArcCurve.html#normal-instance_method) vector was pointing ?

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [August 14, 2021, 4:01pm UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/5 "2021-08-14T16:01:13Z")

</div>

> [@marcosyu](#):
>
> I stumble upon this LISP formula that could help me but unfortunately I don’t have any LISP experience and couldn’t understand it. Could someone help me translate this?
> 
> ```lisp
> ;; Arc to Bulge - Lee Mac
> ;; c - center
> ;; a1,a2 - start, end angle
> ;; r - radius
> ;; Returns: (<vertex> <bulge> <vertex>)
> 
> (defun LM:arc->bulge ( c a1 a2 r )
> (list
> (polar c a1 r)
> ( (lambda ( a ) (/ (sin a) (cos a)))
> (/ (rem (+ pi pi (- a2 a1)) (+ pi pi)) 4.0)
> )
> (polar c a2 r)
> )
> )
> 
> ```

The “sort of” translation to SketchUp Ruby is …

```ruby
# Given a SketchUp ArcCurve object, returns the arc's start point, it's bulge
# and it's end point.
# @param arc_curve [Sketchup::ArcCurve]
# @return [Array<Geom::Point3d, Float, Geom::Point3d>]
def arc_to_bulge( arc_curve )
  pi = Math::PI
  c = arc_curve.center
  r = arc_curve.radius
  # Convert angles from radions to degrees:
  a1 = arc_curve.start_angle.radians
  a2 = arc_curve.end_angle.radians
  #
  start_point = arc_curve.first_edge.start.position
  end_point = arc_curve.last_edge.end.position
  #
  # Define a Lambda (ie, an anonymous function) ...
  func = ->(a) { Math.sin(a) / Math.cos(a) }
  bulge = func.call(
    # ... and immediately call the lambda where the argument is:
    (pi + pi + (a2 - a1)).remainder(pi + pi) / 4.0
  )
  return start_point, bulge, end_point
end

```

I say “sort\_of” because I did not recreate AutoLISP’s [`polar`](http://docs.autodesk.com/ACD/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-6985.htm) function.

* * *

**NOTE** : I did not examine the function (method) for correctness. The example LISP function most likely relies upon assumptions in the AutoCAD geometric model.

For example, what is the assumed angular datum (vector) for the angles and does it matter if it differs in the SketchUp geometric model ?

Also, in SketchUp, a developer can assign whatever angular datum (vector) they wish as the 2nd argument to [`Sketchup::Entities#add_arc`](https://ruby.sketchup.com/Sketchup/Entities.html#add_arc-instance_method), but it is usually set to **`X_AXIS`**.

However, if it is set differently, then **both** the getter methods [`Skethcup::ArcCurve#start_angle`](https://ruby.sketchup.com/Sketchup/ArcCurve.html#end_angle-instance_method) and [`Skethcup::ArcCurve#start_angle`](https://ruby.sketchup.com/Sketchup/ArcCurve.html#end_angle-instance_method) return values **relative** to the arcurve’s [`Skethcup::ArcCurve#xaxis`](https://ruby.sketchup.com/Sketchup/ArcCurve.html#xaxis-instance_method) vector.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [August 14, 2021, 10:36pm UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/6 "2021-08-14T22:36:58Z")

</div>

After spending some time reading up on chords, sagitta, unit circle, bulge, etc., it seems the following would be the simplest …

```ruby
def arc_to_bulge( arc_curve )
  a1 = arc_curve.start_angle # radians
  a2 = arc_curve.end_angle # radians
  ai = a2 - a1 # included angle (radians)
  bulge = Math.tan(ai/4)
  start_point = arc_curve.first_edge.start.position
  end_point = arc_curve.last_edge.end.position
  return start_point, bulge, end_point
end

```

The radius (_`r`_) bisecting the chord and arc forms two equal angles _`θ`_ (theta) and from this we have the half chord equal to …

```ruby
  hc = r * Math.sin(θ)

```

The sagitta _`s`_ is equal to …

```ruby
  s = r * (1 - Math.cos(θ))

```

I’ve verified that the sagitta / half chord ratio equals the tangent of one-quarter of the arc’s included angle:

```ruby
s / hc == Math.tan(ai/4)

```

* * *

**NOTE** : I get a different result for bulge with the translated LISP function mentioned above.

---

<div class="post-metadata">

**Author:** ![marcosyu](https://avatars.discourse-cdn.com/v4/letter/m/53a042/32.png) [@marcosyu](https://forums.sketchup.com/u/marcosyu)\
**Post date:** [August 15, 2021, 8:50am UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/7 "2021-08-15T08:50:10Z")

</div>

```auto
def arc_to_bulge( arc_curve )
  a1 = arc_curve.start_angle # radians
  a2 = arc_curve.end_angle # radians
  ai = a2 - a1 # included angle (radians)
  bulge = Math.tan(ai/4)
  start_point = arc_curve.first_edge.start.position
  end_point = arc_curve.last_edge.end.position
  return start_point, bulge, end_point
end

```

Thanks I think this is much simpler than I have which is getting the included angle from the vectors from the center to the `start_pt` and `end_pt` then subtracting `Math::PI * 2` if its the a major arc. But I’m still encountering the unexpected rotating of the drawing

```auto
Did you take into account the direction that the ArcCurve’s normal vector was pointing ?

```

Are you referring to the vector of the actual bulge? `center_pt to center of the arc line`?

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [August 15, 2021, 11:26am UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/8 "2021-08-15T11:26:29Z")

</div>

> [@marcosyu](#):
>
> Are you referring to the vector of the actual bulge

No, I’m referring to the method **`arc_curve.normal`** `#=> vector of the arc's normal`  
It will point forwards or backwards with respect to the arc and tells you which way the arc is “facing”.  
Basically it also defines the plane of the arc as given any of the arc’s vertices and the normal vector you define a plane. The normal vector is perpendicular to the any geometric object’s plane. (See the explanation in the overview of the [`Geom`](https://ruby.sketchup.com/Geom.html) module.)

---

<div class="post-metadata">

**Author:** ![marcosyu](https://avatars.discourse-cdn.com/v4/letter/m/53a042/32.png) [@marcosyu](https://forums.sketchup.com/u/marcosyu)\
**Post date:** [August 18, 2021, 2:08am UTC](https://forums.sketchup.com/t/lisp-to-math-formula-ruby-code/172667/9 "2021-08-18T02:08:58Z")

</div>

Thanks @DanRathbun  
Marking this as a solution since it solves the question that I ask and together with the clockwise direction formula it now works.
