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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.