3
$\begingroup$

I am trying to make a python script that creates a 3-d graph and automatically puts certain edges in a freestyle line group. So far I am able to create a surface with the code

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
import bpy
import bmesh
import numpy as np


xmin,xmax,ymin,ymax = -3,3,-3,3
N = 30

def f(x,y):
    return (np.sin(2*x)+np.sin(2*y))/2

verts = [Vector((x,y,f(x,y))) for y in np.linspace(ymin, ymax, N) for x in np.linspace(xmin, xmax, N)]
faces = [(i+j*N, i+1+j*N, i+1+(j+1)*N, i+(j+1)*N) for i in range(N-1) for j in range(N-1)]

mesh = bpy.data.meshes.new(name="New Object Mesh")
mesh.from_pydata(verts, [], faces)

mesh.update(calc_edges=True) 

obj = bpy.data.objects.new('new object', mesh)
obj.location = Vector([0,0,0])
scene = bpy.context.scene
scene.objects.link(obj)
scene.objects.active = obj
obj.select = True

I would like every other line of edges to be marked as a freestyle edge. By hand, I would go to edit mode > edges, alt+click on every other edge (to select the whole line of edges) and then do a "Mark Freestyle Edge". However, I would like my script to automatically mark the edges when the mesh is created.

Below is a picture with every other row of edges selected. enter image description here

$\endgroup$
  • $\begingroup$ Nice script. Could you please provide an image of the selection, ( bit confused by "every other edge") and result desired. (even if it's for N = 5) $\endgroup$ – batFINGER Nov 16 '16 at 16:47
  • $\begingroup$ @batFINGER Thanks :-). I've added a picture. My end goal is actually to mark edges whose vertices lie near an integer, but if I can figure out how to mark edges from python at all, I think I can figure out how to do the rest... $\endgroup$ – Jason Siefken Nov 17 '16 at 3:42
  • 1
    $\begingroup$ I think you are looking for object.data.edges[0].use_freestyle_mark $\endgroup$ – sambler Nov 17 '16 at 6:03
  • 1
    $\begingroup$ @sambler yeah that was the easy bit, got a bit stuck on how to select edges to mark. Think there should be a quick way to do this with edge indexes, but it wasn't jumping out at me. $\endgroup$ – batFINGER Nov 17 '16 at 7:31
3
$\begingroup$

To mark a freestyle edge use MeshEdge.use_freestyle_mark

Here is some pretty ugly demo code to select every second line of edges in the x direction, that works because mesh is aligned x, y.

import bpy
import bmesh
from mathutils import Vector

context = bpy.context
mesh = context.object.data
N = 30
TOL = 0.0001

# clear all freestyle mark edges

for e in mesh.edges:
    e.use_freestyle_mark = False

def edge_by_value(e, axis, value):
    v1, v2 = e.verts
    return getattr(v1.co, axis) == getattr(v2.co, axis) and abs(getattr(v2.co, axis) - value ) < TOL

bm = bmesh.new()
bm.from_mesh(mesh)
bm.edges.ensure_lookup_table()

x = -3
while x < 3:

    edges = [e for e in bm.edges if edge_by_value(e, "x", x)]
    print(x, len(edges))
    for e in edges:
        mesh.edges[e.index].use_freestyle_mark = True
        mesh.edges[e.index].select = True # selected 
    # every second edge
    x += 2 * 6 / (N - 1)

mesh.update()

Running with this line of code

    edges = [e for e in bm.edges if edge_by_value(e, "x", x) 
               or edge_by_value(e, "y", x)]

enter image description here

Probably a better approach is: if you know the index order of the edges, would be using row/col integer modulus and div on the edge index.

$\endgroup$

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.