I have object like this:
I want to cut it in half and flatten it to something like plane. In other words I want create flat map of this maze - all simple ways are welcome.
Blender Stack Exchange is a question and answer site for people who use Blender to create 3D graphics, animations, or games. It only takes a minute to sign up.Sign up to join this community
This might work..
It's a script which gets as close as I can to inverting the Simple Deform > Bend modifier.
It's not very general, and makes some assumptions:
Select the object in Object Mode, and run this:
import bpy from math import atan2, sqrt cyl = bpy.context.object if cyl: flt = cyl.copy() me = flt.data.copy() flt.data = me bpy.context.collection.objects.link(flt) min_r = float("inf") for v in me.vertices: x, y, z = v.co r = v.co.xy.length theta = atan2(x, y) v.co = theta, r, z min_r = min(r, min_r) for v in me.vertices: v.co.x *= min_r v.co.y -= min_r flt.location.y += min_r
Which should produce a straightened version (green, derived from blue), scaled and located, ready to be bent back by Simple Deform > Bend.
The Bend modifier uses the bounding box of the straightened object. Because of the gap, the required bend is not quite 360 degrees. In the example .blend, the match is reached at about 356 degrees.
Lurking Pythonistas / bpyists are welcome to improve or correct the style of this script.
Splitting script to bisect first, copy, and then "unfurl" copy and join as shapes
Similarly to a cylindrical UV projection can "unwrap" a cylinder from cylindrical coordinates to flat.
(Just seen RobinBetts excellent answer, doing much the same.)
Some Pre Pro on mesh
Firstly going to be a lot easier to set origin to geometry (bounds) Can also be done via bounding box
which in this case puts it in pipe centre. The xy coordinate vector of any vertex gives its distance from the pipe axis.
Have also removed the coplanar faces of the "nut end". (Would need to be poked to axis line to unfurl nicely)
Bisects the pipe with a cutting plane.
Have arbitrarily chosen the ZY plane to chop the pipe where locally Y > 0 (the top looking down)
Select a vertex as unfurl radius
Run in edit mode. Select a vertex you wish to be the xy radius to unfurl radius
r to XY plane. The height will be the xy radius take r, the Y value the old z value and the x the longitude angle (remember arc length = angle in radians.)
Script. Edit mode select vertex. then run script. (Alters the mesh, so as always backup first / run on copy etc)
import bpy import bmesh from mathutils import Vector from math import copysign, pi context = bpy.context ob = context.object me = ob.data bm = bmesh.from_edit_mesh(me) #bm.from_mesh(me) v_r = bm.select_history.active r = v_r.co.xy.length assert(isinstance(v_r, bmesh.types.BMVert), "Select a Vert") cut = bmesh.ops.bisect_plane( bm, geom=[f for f in bm.faces if all(v.co.y > 0 for v in f.verts)] + [e for e in bm.edges if all(v.co.y > 0 for v in e.verts)] + [v for v in bm.verts if v.co > 0], plane_no=(1, 0, 0), )["geom_cut"] for g in cut: g.select = True bmesh.ops.split_edges( bm, edges=[e for e in cut if isinstance(e, bmesh.types.BMEdge)], verts=[v for v in cut if isinstance(v, bmesh.types.BMVert)], use_verts=True ) # now "unfurl" up = Vector((0, -1)) for v in bm.verts: co = v.co.copy() angle = -up.angle_signed(v.co.xy) if 1 + up.dot(v.co.xy.normalized()) < 1e-4: # meridian fv = sum((f.calc_center_median().x for f in v.link_faces) ) / len(v.link_faces) v.select_set(True) angle = copysign(angle, fv) v.co.y = co.z v.co.z = co.xy.length - r v.co.x = angle * r bmesh.update_edit_mesh(me)
Here is a solution that seems to work:
Give your cylinder a Surface Deform modifier with the plane as Target, click on Bind.
Disable the plane's Simple Deform visibility, the cylinder should flatten.