5
$\begingroup$

Is it possible to create a BMesh polygon (BMFace) with holes via Python?

Use case. I need that for my addons that import geographical data. A polygon for Rome has a hole for Vatican City.

$\endgroup$
2
$\begingroup$

Polygons in Mesh or BMesh aren't permitted to have holes in the sense of providing a perimeter and adding an internal part to subtract. This means considering alternatives.

  1. You can construct an irregular polygon / Ngon.

enter image description here

But it will contain at least two duplicated vertices for that pathway between the cutout and the perimeter.

  1. You could script a mesh.fill(), which could take two given edge outlines and fill from the outer edges inwards. (will add script when I have time)

enter image description here

  1. Alternatively you might use a counter intuitive solution namely a 2D Curve (of straight parts) : code included in link
$\endgroup$
  • $\begingroup$ The solution with the pathway could be tricky to realize for a general case: concave perimeter, multiple concave holes. $\endgroup$ – vvoovv Jul 2 '15 at 17:41
  • $\begingroup$ How would you script that mesh.fill() for the general case: concave perimeter, multiple concave holes? $\endgroup$ – vvoovv Jul 2 '15 at 17:42
  • $\begingroup$ I had to switch off the computer for an electric storm, maybe I can answer later. $\endgroup$ – zeffii Jul 3 '15 at 7:09
1
$\begingroup$

BMesh operator bmesh.ops.triangle_fill does the trick:

bmesh.ops.triangle_fill(bm, use_beauty=True, use_dissolve=False, edges=outer_and_inner_edges)

Here outer_and_inner_edges is the list of BMesh edges (both outer and inner) that constitute the polygon with holes.

The operator will create a bunch of triangles that cover the polygon in question.

$\endgroup$
-1
$\begingroup$

yes, is possible.. you need your vertices and faces data...

here a fast template, you only need to modify your vertices and face data:

this addon set a button in order to add some cube with hole:

cube with hole

bl_info = {
    "name": "bmesh with holes",
    "author": "Diego Quevedo",
    "version": (1, 0),
    "blender": (2, 7, 3),
    "location": "View3D > Add > Mesh > bmesh",
    "description": "Adds a new Mesh Object using bmesh",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "Add Mesh"}


import bpy
from bpy.types import Operator
from bpy.props import FloatVectorProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from mathutils import Vector


def add_object(self, context):
    edges = []
    verts = [(1.0, 0.9999999403953552, -1.0), (1.0, -1.0, -1.0), (-1.0000001192092896, -0.9999998211860657, -1.0), (-0.9999996423721313, 1.0000003576278687, -1.0), (-0.7993143200874329, 7.718172128079459e-07, -1.0), (-0.7839558124542236, -0.1559378057718277, -1.0), (-0.7384703755378723, -0.3058837354183197, -1.0), (-0.6646059155464172, -0.4440747797489166, -1.0), (-0.565200924873352, -0.5652002096176147, -1.0), (-0.44407564401626587, -0.6646053194999695, -1.0), (-0.3058846890926361, -0.7384699583053589, -1.0), (-0.15593880414962769, -0.7839556336402893, -1.0), (-2.6044966716654017e-07, -0.7993143200874329, -1.0), (0.1559382975101471, -0.7839557528495789, -1.0), (0.3058842122554779, -0.738470196723938, -1.0), (0.44407519698143005, -0.6646056175231934, -1.0), (0.5652005672454834, -0.5652005672454834, -1.0), (0.6646056175231934, -0.44407519698143005, -1.0), (0.7384701371192932, -0.3058842122554779, -1.0), (0.7839557528495789, -0.15593838691711426, -1.0), (0.7993143200874329, 6.034655086750718e-08, -1.0), (0.7839556932449341, 0.1559385061264038, -1.0), (0.7384701371192932, 0.30588433146476746, -1.0), (0.6646056175231934, 0.44407519698143005, -1.0), (0.5652005672454834, 0.5652005672454834, -1.0), (0.44407525658607483, 0.6646055579185486, -1.0), (0.30588436126708984, 0.7384701371192932, -1.0), (0.15593849122524261, 0.7839556932449341, -1.0), (0.0, 0.7993143200874329, -1.0), (-0.1559372842311859, 0.7839559316635132, -1.0), (-0.3058832585811615, 0.7384706139564514, -1.0), (-0.4440743327140808, 0.6646061539649963, -1.0), (-0.5651998519897461, 0.5652012825012207, -1.0), (-0.6646050214767456, 0.4440760612487793, -1.0), (-0.7384697794914246, 0.3058851659297943, -1.0), (-0.7839555740356445, 0.15593931078910828, -1.0), (1.0000004768371582, 0.999999463558197, 1.0), (-0.9999999403953552, 1.0, 1.0), (0.9999993443489075, -1.0000005960464478, 1.0), (-1.0000003576278687, -0.9999996423721313, 1.0), (-2.6044966716654017e-07, -0.7993143200874329, 1.0), (-0.15593880414962769, -0.7839556336402893, 1.0), (-0.3058846890926361, -0.7384699583053589, 1.0), (-0.44407564401626587, -0.6646053194999695, 1.0), (-0.565200924873352, -0.5652002096176147, 1.0), (-0.6646059155464172, -0.4440747797489166, 1.0), (-0.7384703755378723, -0.3058837354183197, 1.0), (-0.7839558124542236, -0.1559378057718277, 1.0), (-0.7993143200874329, 7.718172128079459e-07, 1.0), (-0.7839555740356445, 0.15593931078910828, 1.0), (-0.7384697794914246, 0.3058851659297943, 1.0), (-0.6646050214767456, 0.4440760612487793, 1.0), (-0.5651998519897461, 0.5652012825012207, 1.0), (-0.4440743327140808, 0.6646061539649963, 1.0), (-0.3058832585811615, 0.7384706139564514, 1.0), (-0.1559372842311859, 0.7839559316635132, 1.0), (0.0, 0.7993143200874329, 1.0), (0.15593849122524261, 0.7839556932449341, 1.0), (0.30588436126708984, 0.7384701371192932, 1.0), (0.44407525658607483, 0.6646055579185486, 1.0), (0.5652005672454834, 0.5652005672454834, 1.0), (0.6646056175231934, 0.44407519698143005, 1.0), (0.7384701371192932, 0.30588433146476746, 1.0), (0.7839556932449341, 0.1559385061264038, 1.0), (0.7993143200874329, 6.034655086750718e-08, 1.0), (0.7839557528495789, -0.15593838691711426, 1.0), (0.7384701371192932, -0.3058842122554779, 1.0), (0.6646056175231934, -0.44407519698143005, 1.0), (0.5652005672454834, -0.5652005672454834, 1.0), (0.44407519698143005, -0.6646056175231934, 1.0), (0.3058842122554779, -0.738470196723938, 1.0), (0.1559382975101471, -0.7839557528495789, 1.0)]
    faces = [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19), (0, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 4, 3), (36, 0, 3, 37), (0, 36, 38, 1), (1, 38, 39, 2), (2, 39, 37, 3), (36, 37, 39, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55), (36, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 40, 38), (28, 27, 57, 56), (29, 28, 56, 55), (27, 26, 58, 57), (30, 29, 55, 54), (26, 25, 59, 58), (31, 30, 54, 53), (25, 24, 60, 59), (32, 31, 53, 52), (24, 23, 61, 60), (33, 32, 52, 51), (23, 22, 62, 61), (34, 33, 51, 50), (22, 21, 63, 62), (35, 34, 50, 49), (21, 20, 64, 63), (4, 35, 49, 48), (20, 19, 65, 64), (5, 4, 48, 47), (19, 18, 66, 65), (6, 5, 47, 46), (18, 17, 67, 66), (7, 6, 46, 45), (17, 16, 68, 67), (8, 7, 45, 44), (16, 15, 69, 68), (9, 8, 44, 43), (15, 14, 70, 69), (10, 9, 43, 42), (14, 13, 71, 70), (11, 10, 42, 41), (13, 12, 40, 71), (12, 11, 41, 40)]



    try:

        mesh = bpy.data.meshes.new(name="New Object Mesh")
        mesh.from_pydata(verts, edges, faces)
        # useful for development when the mesh may be invalid.
        # mesh.validate(verbose=True)
        object_data_add(context, mesh, operator=self)
    except:
        print("error")


class OBJECT_OT_add_object(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.cube_hole"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}



    def execute(self, context):

        add_object(self, context)

        return {'FINISHED'}


class OBJECT_OT_add_objectPanel(bpy.types.Panel):
    #bl_category = "NN"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    #bl_context = "editmode"
    bl_label = "ADD_OBJ"
    @classmethod
    def poll(cls, context):
        return (context.mode == 'OBJECT' or context.mode == 'EDIT_MESH' )

    def draw(self, context):
        layout = self.layout

        row = layout.row(align=True)
        row.operator(OBJECT_OT_add_object.bl_idname) #THE OPERATOR





def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)


if __name__ == "__main__":
    register()
$\endgroup$
  • $\begingroup$ Link only answers are discouraged as if the link goes down then so does the answer. Please include some of the steps within the answer itself. $\endgroup$ – Ray Mairlot Jul 2 '15 at 16:44
  • $\begingroup$ @vvoovv I update the answer with some fast addon template that you can use $\endgroup$ – yhoyo Jul 2 '15 at 17:49
  • $\begingroup$ @yhoyo I tried your addon. That approach could be very tricky for the general case: concave perimeter, multiple holes $\endgroup$ – vvoovv Jul 2 '15 at 18:12
  • 1
    $\begingroup$ This doesn't appear to answer the question $\endgroup$ – zeffii Jul 3 '15 at 7:16

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.