# How can I create a mathematically correct arc/circular segment?

Given 3 vertices, or a chord and height, how can I create a mathematically correct arc/circular segment with an even distribution of vertices while controlling for the number of vertices.

I frequently need to model arcs in Blender from real-world measurements. Typically I know the cord and height of the arc, giving me 3 points on the full circle.

To create a mathematically correct arc, controlling for the number of vertices, my workflow is as follows:

1. Plug the coordinates of the three vertices into a digital graphics calculator.
2. Retrieve the location of the centre of the full circle, and the angle between the vertices at either end of the cord.
3. Place the cursor at the centre of the full circle in Blender by editing the 3D cursor coordinates.
4. Select one vertex on the chord and use the spin tool, manually entering in the angle retrieved from the graphics calculator and the number of desired vertices.

While this produces an accurate result it is a rather tedious process. How can I achieve this same result using a faster workflow?

The theory is well covered here Calculate the radius of a circle given the chord length and height of a segment

The text editor > Templates > Python > Operator Add Mesh template modified to add an arc.

Input the arc length, arc height and number of segments and it creates an arc.

Notes. Haven't dealt with the restriction that arc height can only ever by at most half chord length for a semi circle.

bl_info = {
"name": "Circular Arc",
"author": "batFINGER",
"version": (1, 0),
"blender": (2, 80, 0),
"location": "View3D > Add > Mesh > Circular Arc",
"description": "Adds a mesh circumcircle given base and height",
"warning": "",
"doc_url": "",
}

import bpy
import bmesh
from mathutils import Matrix
from math import asin

from bpy.props import (
IntProperty,
BoolProperty,
FloatProperty,
)

bl_options = {'REGISTER', 'UNDO'}

length: FloatProperty(
name="length",
description="Chord Length",
min=0.01,
max=100.0,
default=2.0,
unit='LENGTH',
)
height: FloatProperty(
name="Height",
description="Arc Height",
min=0.01,
max=100.0,
unit='LENGTH',
default=1.0,
)
segments: IntProperty(
name="Arc Segments",
description="Number of Segments",
min=1,
default=8,
)

def draw(self, context):
'''Generic Draw'''
layout = self.layout
# annnotated on this class
for prop in self.__class__.__annotations__.keys():
layout.prop(self, prop)
layout.prop(self, prop)

def execute(self, context):
h = self.height
a = self.length / 2
r = (a * a + h * h) / (2 * h)
if abs(a / r) > 1:
# math domain error on arcsin
return {'CANCELLED'}
angle = 2 * asin(a / r)

mesh = bpy.data.meshes.new("Arc")

bm = bmesh.new()
v = bm.verts.new((0, r, 0))
bmesh.ops.rotate(
bm, verts=[v], matrix=Matrix.Rotation(angle / 2, 3, 'Z'))
bmesh.ops.spin(
bm,
geom=[v],
axis=(0, 0, 1),
steps=self.segments,
angle=-angle,
)

for v in bm.verts:
v.co.y -= r - h
v.select = True
bm.to_mesh(mesh)
#mesh.update()

# add the mesh as an object into the scene with this utility module
from bpy_extras import object_utils

return {'FINISHED'}

def register():

def unregister():

if __name__ == "__main__":
register()

# test call

• Works amazingly. Thanks! Should definitely be added to the bundled "Extra Objects" add-on. Mar 9 '19 at 22:09
• Maybe, in the spirit of this add-on, make an add-on to place the 3D cursor at the circumcenter (sorry, circumcentre) of 3 objects, or 3 vertices? .. it would be very useful.. maybe it exists somewhere else that doesn't involve hauling in too much clobber with it, I don't know. Jun 25 '20 at 8:37
• Similar to ?? Fixed above to install as addon and put length in units. Had a look at getting a 0.5 chord to bay a window gap (in edit mode) and appears there is some miscalc. Adding a chord of edges between two verts could also be considered I suppose. Missed with every bullet so far Robin. Noticed a couple of questions re stools that would be right down your alley.. I had so many, small mercy I went for extruding solids over any mention of fluids. Jun 25 '20 at 9:35
• @RobinBetts (Sure I have done something with this on here before, cannot find) Anyhoo Using en.wikipedia.org/wiki/… script to add circumcircle Run with 3 objects are selected. pasteall.org/M4cX Jun 25 '20 at 11:29
• @batFINGER I thought you had, too.. didn't think it would be much work for you. There was I, chugging away, out of interest, seeing what I could do myself. Actually chose the same route as you.. not too bad.. but then received this lesson in bpy, and idiomatic Python :D. Jun 25 '20 at 13:31
1. Insert a plane with the edge length matching your chord's length;
2. Remove the plane's two opposite vertices to have a segment;
3. Subdivide the segment the odd number of times;
4. Use proportional editing with the circular fall-off, the middle vertex selected, and move everything along Z axis to the desired height.

You may also join the opposite ends of your arc creating an edge if needed.

• For the purposes of this question I'm interested in creating mathematically accurate arcs as opposed to eyeballing approximations. Mar 9 '19 at 12:41
• With arcs and circles it's always an approximation as there's this pi number. And if you input given values, approximated as well, exactly you get the result. Mar 9 '19 at 13:18