Featured post

new redirect for blender.org bpy docs.

http://www.blender.org/api/blender_python_api_current/ As of 10/11 november 2015 we can now link to the current api docs and not be worr...

January 01, 2015

Getting the center of a circle, given an incomplete circle


figure 1. shows circle obtain from 3 verts minimum.

Missing convenience for semi high precision modelling

Periodically I miss the most elementary CAD features in Blender. While Blender is not designed for ultra high precision modeling, there's still room for precision before resorting to simply "eye-balling" it. Core developers are busy making Blender awesome in other ways, so instead of sidetracking them I like to experiment and learn how to make these tools myself. Whatever, I just need this stuff and don't want to wait.

Additions to tinyCAD

Blender doesn't keep track of origins / centers of its primitives. For circles, let's not beat around the bush, this is highly annoying. Once you edit or move a circle mesh you lose the ability to change its parameters. Often I need to find the center of a circle after some of its vertices have been deleted. If you still have 3 points, the origin can be found easily using trigonometry. I'll add this to the tinyCAD. My implementation will work on either selecting two adjacent edges, or 3 vertices (not necessarily adjacent)

edit

This is now added to the github version as 'Circle Centers', prior to updating the addons/contrib version.

The following code is the least bit of code you need to get the circle center from 3 verts using trig.
import bpy
import bmesh
import math
import mathutils
from mathutils import geometry
from mathutils import Vector


def generate_3PT_mode_1(pts=[]):

    verts, edges = [], []
    V = Vector

    # construction
    v1, v2, v3, v4 = V(pts[0]), V(pts[1]), V(pts[1]), V(pts[2])
    edge1_mid = v1.lerp(v2, 0.5)
    edge2_mid = v3.lerp(v4, 0.5)
    axis = geometry.normal(v1, v2, v4)
    mat_rot = mathutils.Matrix.Rotation(math.radians(90.0), 4, axis)

    # triangle edges
    v1_ = ((v1 - edge1_mid) * mat_rot) + edge1_mid
    v2_ = ((v2 - edge1_mid) * mat_rot) + edge1_mid
    v3_ = ((v3 - edge2_mid) * mat_rot) + edge2_mid
    v4_ = ((v4 - edge2_mid) * mat_rot) + edge2_mid

    r = geometry.intersect_line_line(v1_, v2_, v3_, v4_)
    if r:
        # for general use this requires:   matrix_local * p1
        p1, _ = r
        bpy.context.scene.cursor_location = p1

    else:
        print('not on a circle')

    return verts, edges


def get_three_verts_from_selection(obj):

    me = obj.data
    bm = bmesh.from_edit_mesh(me)

    if hasattr(bm.verts, "ensure_lookup_table"):
        bm.verts.ensure_lookup_table()
        bm.edges.ensure_lookup_table()
    
    return [v.co[:] for v in bm.verts if v.select]


obj = bpy.context.object
pts = get_three_verts_from_selection(obj)
generate_3PT_mode_1(pts)