1
$\begingroup$

question based on this topic Using python and bmesh to scale/resize a face in place where each face was scaled separately.

So actually the question in the title. I'm newbie to python. I tried to find connected faces based on the same vertex indexes, then calculate the average mean of the vertices positions included this faces(like a origin point). But it works only for single group faces, how to make it for multiple group faces?

import bpy
import bmesh
import numpy as np
from mathutils import Vector as vec

#EDIT mode#
me = bpy.context.edit_object.data
bm = bmesh.from_edit_mesh(me)
scale_factor = 0.5

seleted_vert_group = []
verts_co_x = []
verts_co_y = []
verts_co_z = []

#checking for matches
for face1 in bm.select_history:
    passwither = 0 #pass double matched face
    for face2 in bm.select_history:
        if face1 == face2:
            continue
        for vert1 in face1.verts: 
            for vert2 in face2.verts:
                if passwither == 1:
                    continue
                if vert1.index == vert2.index:
                    passwither = 1
                    print(f'face index: {face1.index}')
                    for vert in face1.verts:
                        seleted_vert_group.append(vert)
                        verts_co_x.append(vert.co.x)
                        verts_co_y.append(vert.co.y)
                        verts_co_z.append(vert.co.z)

co_x = np.sum(verts_co_x)/len(verts_co_x)
co_y = np.sum(verts_co_y)/len(verts_co_y)
co_z = np.sum(verts_co_z)/len(verts_co_z)
origin_point = vec((co_x,co_y,co_z))
 
for vert in set(seleted_vert_group):
    vert.co = origin_point + scale_factor * (vert.co - origin_point)

bmesh.update_edit_mesh(me)
$\endgroup$
0
$\begingroup$

Find connected islands

enter image description here

  • Tag all selected faces as false
  • Pop one selected face tag as true
  • Yield recursively to find all selected and connected faces (an island)
  • Scale the verts of the island based on average vert loc. (Could use face centers instead)
  • Remove the island from selected set

See image on how this may not work as expected for faces touching at vertex corners.

import bpy
import bmesh
from mathutils import Vector, Matrix

#EDIT mode#
me = bpy.context.edit_object.data
bm = bmesh.from_edit_mesh(me)
scale_factor = 0.5

faces = set(f for f in bm.faces if f.select)

def walk_island(face):
    face.tag = True
    yield face
    faces = [f for e in face.edges for f in e.link_faces if not f.tag and f.select]
    for f in faces:
        yield from walk_island(f)

def scale(island):
    verts = set(v for f in island for v in f.verts)
    bmesh.ops.scale(
        bm,
        verts=list(verts),
        vec=(scale_factor,) * 3,
        space=Matrix.Translation(
            sum((-v.co for v in verts), Vector()) / len(verts)
            ))   

for f in faces:
    f.tag = False
    
while faces:
    f = faces.pop()
    island = set(walk_island(f))
    scale(island)
    faces -= island
    
bmesh.update_edit_mesh(me)
$\endgroup$
0
$\begingroup$

Hi you should move back them into first position.

I answered based on this question

enter image description here

import bpy
import bmesh

context = bpy.context


ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)
scale_factor = 0.5

for face in bm.select_history:
        center = face.calc_center_median()
        for v in face.verts:
            v.co = center + scale_factor * (v.co - center)

bmesh.update_edit_mesh(me)
$\endgroup$
1
  • $\begingroup$ The problem this method is that the connected edges will have a double scale $\endgroup$ – day9 Sep 4 '20 at 19:57

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.