3
$\begingroup$

I would like to make an simple angle label such as this:

image

using the python script to construct it.

The problem is trying to spin a MeshVertex, as the code looks for a Mesh object instead when using the bpy.ops.mesh.spin function.

The best method I have found to do this is to subdivide a small cylinder (vector) to get vertices, then select a vertice along the cylinder, then to spin it around the origin with some theta.

Here is the code I have so far, which does not work:

import bpy
import math
import os
import unicodedata

import bmesh
from bmesh.ops import spin

pi = math.pi

def lathe_geometry(bm, cent, axis, dvec, angle, steps, remove_doubles=True, dist=0.0001):
    geom = bm.verts[:] + bm.edges[:]

    # super verbose explanation.
    spin(
        bm, 
        geom=geom,         # geometry to use for the spin
        cent=cent,         # center point of the spin world
        axis=axis,         # axis, a (x, y, z) spin axis
        dvec=dvec,         # offset for the center point
        angle=angle,       # how much of the unit circle to rotate around
        steps=steps,       # spin subdivision level 
        use_duplicate=0)   # include existing geometry in returned content

    if remove_doubles:
        bmesh.ops.remove_doubles(bm, verts=bm.verts[:], dist=dist)

theta = pi/4

bpy.ops.mesh.primitive_cylinder_add( \
    radius=0.01, \
    depth = 5,
    view_align=False, \
    location = (0,5,0), \
    rotation = (pi/2, pi/2, pi/2+theta))





c1 = bpy.context.scene.objects.active = bpy.data.objects['Cylinder']
c1.select = True


bpy.ops.object.mode_set(mode='EDIT', toggle=False) 
bpy.ops.mesh.subdivide(number_cuts=10)

bpy.ops.object.mode_set(mode='OBJECT', toggle=False) 
c1.select = False

for el in c1.data.vertices:
       el.select = False

vert = c1.data.vertices[3]
vert.select = True

bm = bmesh.new()
bm.from_mesh(c1.data)

axis = (1,0,0)
dvec = (0,0,0)
angle = 2*math.pi
steps = 20
cent = c1.location

lathe_geometry(bm, cent, axis, dvec, angle, steps, remove_doubles=True, dist=0.0001)

bm.to_mesh(c1.data)
bm.free()
$\endgroup$

1 Answer 1

4
$\begingroup$

The api doc specifies the argument geom as

geom (list of (bmesh.types.BMVert, bmesh.types.BMEdge, bmesh.types.BMFace))

so

import bpy
import bmesh
from math import radians
from mathutils import Vector, Quaternion

mesh = bpy.data.meshes .new("Pie")
obj  = bpy.data.objects.new("Pie", mesh)

scene = bpy.context.scene
scene.objects.link(obj)

bm = bmesh.new()

A = bm.verts.new(Vector((0.0, 0.0, 0.0)))
B = bm.verts.new(Vector((1.0, 0.0, 0.0)))
base_line = bm.edges.new((A, B))

result = bmesh.ops.spin(
    bm,
    geom  = [B],
    cent  = A.co,
    axis  = Vector((0.0, 0.0, 1.0)), 
    dvec  = Vector((0.0, 0.0, 0.0)),
    angle = radians(60.0),
    steps = 12,
    use_duplicate = 0
    )   

C = result['geom_last'][0]
bm.edges.new((C, A))

bm.to_mesh(mesh)
bm.free()

works for me. You could also implement this yourself:

def create_arc(bm, start, center, axis, angle, steps):
    angle = angle / steps
    q = Quaternion(axis, angle)

    prev = start
    vec  = start.co - center

    for i in range(steps):
        vec.rotate(q)
        current = bm.verts.new(center + vec)
        bm.edges.new((prev, current))
        prev = current

    return current
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .