Skip to main content
added 154 characters in body
Source Link
batFINGER
  • 85.2k
  • 10
  • 114
  • 244

Recommend using bmesh for this. Where instead of splines, use edges. The vertices in the same location as the spline points. Manipulate the bmesh via the API and then convert to curve. If there was a bcurve module would use that, but there isn't and curve edit operators are designed to drive one bonkers.

In the test script below, for part 1 I've used the ballall of stringthe string curves to make one bmesh, from the transformed points of all bits of string. Would change up the creation script in question to create a bmesh in first place, for answer sake I've scripted to use the curves created via the script in question.

All edges which have a vertex in the positive quadrant are selected. The selection is then bisected by one of the 3 axis planes. The resulting geometry bisected again and again by other two axes. This will add a vertex aton each cutting pointsedge that crosses the planes.

Recommend using bmesh for this. Where instead of splines, use edges. The vertices in the same location as the spline points.

In the test script below, for part 1 I've used the ball of string curves to make one bmesh, from the transformed points of all bits of string. Would change up the creation script in question to create a bmesh in first place, for answer sake I've scripted to use the curves created via the script in question.

All edges which have a vertex in the positive quadrant are selected. The selection is then bisected by one of the 3 axis planes. The resulting geometry bisected again by other two axes. This will add a vertex at each cutting points.

Recommend using bmesh for this. Where instead of splines, use edges. The vertices in the same location as the spline points. Manipulate the bmesh via the API and then convert to curve. If there was a bcurve module would use that, but there isn't and curve edit operators are designed to drive one bonkers.

In the test script below, for part 1 I've used all of the string curves to make one bmesh. Would change up the creation script in question to create a bmesh in first place, for answer sake I've scripted to use the curves created via the script in question.

All edges which have a vertex in the positive quadrant are selected. The selection is then bisected by one of the 3 axis planes. The resulting geometry bisected again and again by other two axes. This will add a vertex on each edge that crosses the planes.

Source Link
batFINGER
  • 85.2k
  • 10
  • 114
  • 244

Using bmesh.

enter image description here

Recommend using bmesh for this. Where instead of splines, use edges. The vertices in the same location as the spline points.

In the test script below, for part 1 I've used the ball of string curves to make one bmesh, from the transformed points of all bits of string. Would change up the creation script in question to create a bmesh in first place, for answer sake I've scripted to use the curves created via the script in question.

All edges which have a vertex in the positive quadrant are selected. The selection is then bisected by one of the 3 axis planes. The resulting geometry bisected again by other two axes. This will add a vertex at each cutting points.

Next all edges that have both verts in the positive quadrant are removed and the subsequent mesh converted to a curve. I've used the operator here for example sake. Your question already displays how this is done via API.

The resulting curve object has multiple splines rather than being multiple objects, see note below.

import bpy
import bmesh

context = bpy.context
#PART 1 load all single splne curves to one bmesh
scene = context.scene
bm = bmesh.new()
curves = [o for o in scene.objects if o.type == 'CURVE']
for c in curves:
    verts = [bm.verts.new(p.co.xyz) for p in c.data.splines[0].points[1:-1]]
    for i in range(len(verts) - 1):
        bm.edges.new((verts[i], verts[i + 1]))
    bmesh.ops.transform(bm, verts=verts, matrix=c.matrix_world)

# select all edges with a vert in pos quadrant
def is_inquadrant(v):
    return all(getattr(v.co, axis)  >= -1e-4 for axis in "xyz")
    
geom = [e for e in bm.edges if any(is_inquadrant(v) for v in e.verts)]

# bisect the selection by three axis planes
ret = bmesh.ops.bisect_plane(bm, 
            geom=geom, 
            plane_no=(0, 0, 1), 
            plane_co=(0, 0, 0))
ret = bmesh.ops.bisect_plane(bm, 
            geom=ret['geom'], 
            plane_no=(0, 1, 0), 
            plane_co=(0, 0, 0))
ret = bmesh.ops.bisect_plane(bm, 
            geom=ret['geom'], 
            plane_no=(1, 0, 0), 
            plane_co=(0, 0, 0))
# Now have new verts on cuts, select edges with both verts in quad            
for v in bm.verts:
    v.select = False
for e in bm.edges:
    e.select = all(is_inquadrant(v) for v in e.verts)
# remove them    
geom = [e for e in bm.edges if e.select]
bmesh.ops.delete(bm, geom=geom, context=2)
me = bpy.data.meshes.new("BallEdgeMesh")
bm.to_mesh(me)

bm.free()

# add as mesh to scene.

ob = bpy.data.objects.new("BallMesh", me)
scene.objects.link(ob)
scene.objects.active = ob
ob.select = True
# convet to curve
bpy.ops.object.convert(target='CURVE')
curveData = context.object.data
curveData.dimensions = '3D'
curveData.resolution_u = 2
curveData.fill_mode = 'FULL'
curveData.bevel_depth = 0.02
for s in context.object.data.splines:
    s.use_smooth = True
    s.type = 'NURBS'

Note:

If you must have one object for each string: It would be more efficient to make only one "string" curve object (bpy.data.curves) and link to each object instance. Using methods similar to above would only need to add a new curve if it is bisected.

Finally welcome to bse, and kudos on writing a great first question.