I’m writing a script that will read data from a file, and use the data to create a polygon.
There isn’t a way to from the user menu to create an n-sided polygon, at least not from what I can tell. I also did not find a way to create one in the Blender python API. Any suggestions or secret workarounds?
There’s actually the built-in Add > Mesh > Circle opeator:
bpy.ops.mesh.primitive_circle_add(vertices=7, radius=1, fill_type=‘NGON’, location=(0, 0, 0), rotation=(0, 0, 0))
And with python, there are at least 2 ways. I recommend using the bmesh module, as you won’t need to deal with loops and stuff yourself:
http://www.blender.org/documentation/blender_python_api_2_68_5/bmesh.html
Here’s an example script:
import bpy
import bmesh
from math import *
from mathutils import Vector
from bpy.props import IntProperty, FloatProperty
def main(self, context):
step = self.angle_max / self.segments
if context.mode == 'EDIT_MESH':
ob = context.object
bm = bmesh.from_edit_mesh(ob.data)
offset = context.scene.cursor_location - ob.location
else:
bm = bmesh.new()
offset = Vector()
verts = []
verts.append(bm.verts.new(offset))
angle = 0
for i in range(self.segments):
rad = radians(angle)
verts.append(bm.verts.new((sin(rad)*self.radius+offset.x, cos(rad)*self.radius+offset.y, offset.z)))
angle += step
rad = radians(self.angle_max)
verts.append(bm.verts.new((sin(rad)*self.radius+offset.x, cos(rad)*self.radius+offset.y, offset.z)))
faces = [bm.faces.new(verts)]
if self.thickness != 0.0:
geom = bmesh.ops.extrude_face_region(bm, geom=faces)
verts_extruded = [v for v in geom['geom'] if isinstance(v, bmesh.types.BMVert)]
bmesh.ops.translate(bm, verts=verts_extruded, vec=(0,0,self.thickness))
verts.extend(verts_extruded)
bm.normal_update()
if bm.is_wrapped:
bpy.ops.mesh.select_all(action='DESELECT')
for v in verts:
v.select = True
bm.select_flush(True)
if bm.is_wrapped:
bmesh.update_edit_mesh(context.object.data)
else:
me = bpy.data.meshes.new("CircleSegment")
bm.to_mesh(me)
ob = bpy.data.objects.new("CircleSegment", me)
ob.location = context.scene.cursor_location
if bpy.ops.object.select_all.poll():
bpy.ops.object.select_all(action="DESELECT")
bpy.context.scene.objects.link(ob)
bpy.context.scene.objects.active = ob
ob.select = True
bpy.context.scene.update()
class MESH_OT_primitive_circle_segment_add(bpy.types.Operator):
"""Tooltip"""
bl_idname = "mesh.primitive_circle_segment_add"
bl_label = "Add Circle Segment"
bl_options = {'REGISTER', 'UNDO'}
segments = IntProperty(name="Segments", min=1, soft_max=50, default=6)
angle_max = IntProperty(name="Segment angle", min=1, max=359, default=90, subtype='ANGLE')
radius = FloatProperty(name="Radius", min=0.01, soft_max=100, default=5, step=10)
thickness = FloatProperty(name="Thickness", soft_min=-100, soft_max=100, default=1, step=10)
@classmethod
def poll(cls, context):
return True
def execute(self, context):
main(self, context)
return {'FINISHED'}
def register():
bpy.utils.register_module(__name__)
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()
Thanks for the reply.
I should have been more precise about what I am trying to do - an irregular polygon is what I’m trying to create - something like this
but with far more points.
(image is much larger than needed)
Simplified script that actually creates that shape:
import bpy, bmesh
verts = ((0, 3),(2.5, 0.5),(5, 1),(4.5, 3.5),(10.5, 2),(8, 10),(7, 4.5),(2, 6))
bm = bmesh.new()
for v in verts:
bm.verts.new((v[0], v[1], 0))
bm.faces.new(bm.verts)
bm.normal_update()
me = bpy.data.meshes.new("")
bm.to_mesh(me)
ob = bpy.data.objects.new("", me)
bpy.context.scene.objects.link(ob)
bpy.context.scene.update()
Thank you. Once I get the json to python objects script working, I’ll use the sample you provided - it looks like it will do exactly what I need!
This is working near perfect. Some of the faces are not being created correctly - I need to look into that.
One thing I am not able to figure out is to set the origin of the mesh. By default it is at 0,0,0 - but I would like to change it to the MEDIAN, which I attempted to do, but was not successful. (I don’t have the script with me, but it was bpy.ops… pivot point??? ).
I did it manually in the UI and then copied the same function and placed it in the script.
bpy.ops.object.origin_set(type=‘ORIGIN_GEOMETRY’, center=‘MEDIAN’)
but beware, IIRC the behavior differs in object and editmode. You could also transform the mesh with bmesh module (translation matrix) and change the object’s location - same effect. But you need to calculate the median first of course.
That’s the function I’m calling with those parameters - but the origin is not moving to the ‘median’ of the object.
Never mind, found one of your other posts and figured it out.
Needed to select the object first in the scene.