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

3 Answers 3

3
$\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$
3
  • $\begingroup$ The solution with the pathway could be tricky to realize for a general case: concave perimeter, multiple concave holes. $\endgroup$
    – vvoovv
    Commented Jul 2, 2015 at 17:41
  • $\begingroup$ How would you script that mesh.fill() for the general case: concave perimeter, multiple concave holes? $\endgroup$
    – vvoovv
    Commented Jul 2, 2015 at 17:42
  • $\begingroup$ I had to switch off the computer for an electric storm, maybe I can answer later. $\endgroup$
    – zeffii
    Commented Jul 3, 2015 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$
4
  • $\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$ Commented Jul 2, 2015 at 16:44
  • $\begingroup$ @vvoovv I update the answer with some fast addon template that you can use $\endgroup$
    – yhoyo
    Commented Jul 2, 2015 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
    Commented Jul 2, 2015 at 18:12
  • 1
    $\begingroup$ This doesn't appear to answer the question $\endgroup$
    – zeffii
    Commented Jul 3, 2015 at 7:16

You must log in to answer this question.

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