2
$\begingroup$

Is there a simple way to create a circle which contains a hole / inner radius. Ideally where I can dynamically set the inner radius when adding (in the same way I can set outer radius when adding a circle mesh).

I can manually create it by adding a circle with no fill, cloning, scaling down, then creating the faces (see attached), but that is tedious and error prone. I could also do it by creating a circle with triangle fan, clone the out edge down, and the delete middle, but again, that is a bit tedious and makes it difficult to get an exact inner radius.

Is there a way to do this natively in Blender, or via an addon?

enter image description here

$\endgroup$
  • 1
    $\begingroup$ From a circle, in edit mode select the vertices, then E+S (to extrude and scale). $\endgroup$ – lemon Jul 22 at 17:20
  • $\begingroup$ Good answers below, but for the one-off .. Triangle-filled created to radius, all selected, I Inset region with a numerical entry for thickness. X delete center faces? $\endgroup$ – Robin Betts Jul 22 at 17:33
8
$\begingroup$

Add new object mesh addon template

enter image description here

Quick little addon slapped together using text editor > templates > python > Addon Add Object template.

  • Adds two circles, bridges the edge loops.
  • If ngon fill is chosen, splits one fill edge, dissolves the rest.

Test addon.

bl_info = {
    "name": "New 2D Ring",
    "author": "batFINGER",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "View3D > Add > Mesh > New 2D Ring",
    "description": "Adds a 2D ring (circle with hole)",
    "warning": "",
    "wiki_url": "",
    "category": "Add Mesh",
}
import bpy
import bmesh

from bpy_extras.object_utils import AddObjectHelper

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


class MESH_OT_primitive_ring_add(AddObjectHelper, bpy.types.Operator):
    """Add a 2D filled ring mesh"""
    bl_idname = "mesh.primitive_ring_add"
    bl_label = "Add 2D Filled Ring"
    bl_options = {'REGISTER', 'UNDO'}

    inner_radius: FloatProperty(
        name="Inner Radius",
        description="Inner Radius",
        min=0,
        default=1.0,
    )
    outer_radius: FloatProperty(
        name="Outer Radius",
        description="Outer Radius",
        min=0,
        default=2.0,
    )
    segments: IntProperty(
        name="Segments",
        description="Number of Segments",
        min=3,
        default=8,
    )
    ngon_fill: BoolProperty(
        name="Ngon Fill",
        description="Fill with ngon",
    )

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

    def execute(self, context):

        me = bpy.data.meshes.new("CircleHole")

        bm = bmesh.new()
        bmesh.ops.create_circle(bm, radius=self.inner_radius, segments=self.segments)
        bmesh.ops.create_circle(bm, radius=self.outer_radius, segments=self.segments)

        ret = bmesh.ops.bridge_loops(bm, edges=bm.edges)
        if self.ngon_fill:
            edges = ret['edges']
            e = edges.pop()
            bmesh.ops.split_edges(bm, edges=[e])
            bmesh.ops.dissolve_edges(bm,
                                     edges=edges)
        bm.to_mesh(me)
        me.update()

        from bpy_extras import object_utils
        object_utils.object_data_add(context, me, operator=self)

        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator(MESH_OT_primitive_ring_add.bl_idname, icon='MESH_CUBE')


def register():
    bpy.utils.register_class(MESH_OT_primitive_ring_add)

    bpy.types.VIEW3D_MT_mesh_add.append(menu_func)


def unregister():
    bpy.utils.unregister_class(MESH_OT_primitive_ring_add)
    bpy.types.VIEW3D_MT_mesh_add.remove(menu_func)


if __name__ == "__main__":
    register()

    # test call
    #bpy.ops.mesh.primitive_ring_add()

Add Cone Primitive

enter image description here

Though I would add that the functionality is very similar to add cone primitive, with no fill and no height (can scale totally to zero in z and apply)

$\endgroup$
  • 2
    $\begingroup$ This is awesome. I was actually starting to build my own but you beat me to it. Do you plan to release it outside of stackoverflow? Seems like it would be super useful. $\endgroup$ – mikechambers Jul 22 at 22:52
6
$\begingroup$

Maybe its a good subject for the new 2.8 gyzmos!

Create an edge with two vertices corresponding to the inner and outer part of your disk.

Choose the spin tool.

Rotate as you want.

Tune the result with the operator panel.

enter image description here

$\endgroup$
3
$\begingroup$

One way to work around it natively is to create a mesh with only two vertex and an edge connecting them.

Place them strategically like along the X axis so you can control vertex position from the properties panel. Their X coordinate will directly control absolute radius for inner and outer circles quite easily.

Then just add a screw modifier to the mesh. You can control curve resolution and spin angle non-destructively from there.

enter image description here

You can copy this object around instead of adding new ones, for easy duplication

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.