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$
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$

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.