Source code for fabex.utilities.curve_utils
import bpy
from .chunk_builder import (
CamPathChunkBuilder,
)
from .logging_utils import log
from .shapely_utils import chunks_to_shapely
from .simple_utils import (
activate,
progress,
)
from ..exception import CamException
[docs]
def curve_to_shapely(cob, use_modifiers=False):
"""Convert a curve object to Shapely polygons.
This function takes a curve object and converts it into a list of
Shapely polygons. It first breaks the curve into chunks and then
transforms those chunks into Shapely-compatible polygon representations.
The `use_modifiers` parameter allows for additional processing of the
curve before conversion, depending on the specific requirements of the
application.
Args:
cob: The curve object to be converted.
use_modifiers (bool): A flag indicating whether to apply modifiers
during the conversion process. Defaults to False.
Returns:
list: A list of Shapely polygons created from the curve object.
"""
chunks = curve_to_chunks(cob, use_modifiers)
polys = chunks_to_shapely(chunks)
return polys
[docs]
def mesh_from_curve(o, use_modifiers=False):
activate(o)
bpy.ops.object.duplicate()
bpy.ops.object.parent_clear(type="CLEAR_KEEP_TRANSFORM")
co = bpy.context.active_object
# support for text objects is only and only here, just convert them to curves.
if co.type == "FONT":
bpy.ops.object.convert(target="CURVE", keep_original=False)
elif co.type != "CURVE": # curve must be a curve...
bpy.ops.object.delete() # delete temporary object
raise CamException("Source Curve Object Must Be of Type Curve")
co.data.dimensions = "3D"
co.data.bevel_depth = 0
co.data.extrude = 0
co.data.resolution_u = 100
# first, convert to mesh to avoid parenting issues with hooks, then apply locrotscale.
bpy.ops.object.convert(target="MESH", keep_original=False)
if use_modifiers:
eval_object = co.evaluated_get(bpy.context.evaluated_depsgraph_get())
newmesh = bpy.data.meshes.new_from_object(eval_object)
oldmesh = co.data
co.modifiers.clear()
co.data = newmesh
bpy.data.meshes.remove(oldmesh)
try:
bpy.ops.object.transform_apply(location=True, rotation=False, scale=False)
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
except:
pass
return bpy.context.active_object
[docs]
def mesh_from_curve_to_chunk(object):
object = mesh_from_curve(object) if object.type == "CURVE" else object
mesh = object.data
chunks = []
chunk = CamPathChunkBuilder()
ek = mesh.edge_keys
d = {}
for e in ek:
d[e] = 1
dk = d.keys()
x = object.location.x
y = object.location.y
z = object.location.z
lastvi = 0
vtotal = len(mesh.vertices)
perc = 0
log.info("-")
progress(f"Processing Curve - START")
log.info(f"Vertices: {vtotal}")
for vi in range(0, len(mesh.vertices) - 1):
co = (mesh.vertices[vi].co + object.location).to_tuple()
if not dk.isdisjoint([(vi, vi + 1)]) and d[(vi, vi + 1)] == 1:
chunk.points.append(co)
else:
chunk.points.append(co)
# this was looping chunks of length of only 2 points...
if len(chunk.points) > 2 and (
not (dk.isdisjoint([(vi, lastvi)])) or not (dk.isdisjoint([(lastvi, vi)]))
):
chunk.closed = True
chunk.points.append((mesh.vertices[lastvi].co + object.location).to_tuple())
# add first point to end#originally the z was mesh.vertices[lastvi].co.z+z
lastvi = vi + 1
chunk = chunk.to_chunk()
chunk.dedupe_points()
if chunk.count() >= 1:
# dump single point chunks
chunks.append(chunk)
chunk = CamPathChunkBuilder()
progress("Processing Curve - FINISHED")
vi = len(mesh.vertices) - 1
chunk.points.append(
(
mesh.vertices[vi].co.x + x,
mesh.vertices[vi].co.y + y,
mesh.vertices[vi].co.z + z,
)
)
if not (dk.isdisjoint([(vi, lastvi)])) or not (dk.isdisjoint([(lastvi, vi)])):
chunk.closed = True
chunk.points.append(
(
mesh.vertices[lastvi].co.x + x,
mesh.vertices[lastvi].co.y + y,
mesh.vertices[lastvi].co.z + z,
)
)
chunk = chunk.to_chunk()
chunk.dedupe_points()
if chunk.count() >= 1:
# dump single point chunks
chunks.append(chunk)
return chunks
[docs]
def curve_to_chunks(o, use_modifiers=False):
co = mesh_from_curve(o, use_modifiers)
chunks = mesh_from_curve_to_chunk(co)
co = bpy.context.active_object
bpy.ops.object.select_all(action="DESELECT")
bpy.data.objects[co.name].select_set(True)
bpy.ops.object.delete()
return chunks