blendercam/scripts/addons/cam/opencamlib/opencamlib.py

199 wiersze
7.1 KiB
Python

# used by OpenCAMLib sampling
import bpy
try:
import ocl
except ImportError:
try:
import opencamlib as ocl
except ImportError:
pass
import os
import tempfile
import numpy as np
from subprocess import call
from cam.collision import BULLET_SCALE
from cam import simple
from cam.chunk import camPathChunk
from cam.simple import *
from cam.async_op import progress_async
from shapely import geometry as sgeometry
from .oclSample import get_oclSTL
from cam import utils
from cam.opencamlib.oclSample import ocl_sample
OCL_SCALE = 1000.0
PYTHON_BIN = None
def pointSamplesFromOCL(points, samples):
for index, point in enumerate(points):
point[2] = samples[index].z / OCL_SCALE
def chunkPointSamplesFromOCL(chunks, samples):
s_index = 0
for ch in chunks:
ch_points=ch.count()
z_vals=np.array([p.z for p in samples[s_index:s_index+ch_points]])
z_vals /= OCL_SCALE
ch.setZ(z_vals)
s_index+=ch_points
# p_index = 0
# for point in ch.points:
# if len(point) == 2 or point[2] != 2:
# z_sample = samples[s_index].z / OCL_SCALE
# ch.points[p_index] = (point[0], point[1], z_sample)
# # print(str(point[2]))
# else:
# ch.points[p_index] = (point[0], point[1], 1)
# p_index += 1
# s_index += 1
def chunkPointsResampleFromOCL(chunks, samples):
s_index = 0
for ch in chunks:
ch_points=ch.count()
z_vals=np.array([p.z for p in samples[s_index:s_index+ch_points]])
z_vals /= OCL_SCALE
ch.setZ(z_vals)
s_index+=ch_points
# s_index = 0
# for ch in chunks:
# p_index = 0
# for point in ch.points:
# if len(point) == 2 or point[2] != 2:
# z_sample = samples[s_index].z / OCL_SCALE
# ch.points[p_index] = (point[0], point[1], z_sample)
# # print(str(point[2]))
# else:
# ch.points[p_index] = (point[0], point[1], 1)
# p_index += 1
# s_index += 1
def exportModelsToSTL(operation):
file_number = 0
for collision_object in operation.objects:
activate(collision_object)
bpy.ops.object.duplicate(linked=False)
# collision_object = bpy.context.scene.objects.active
# bpy.context.scene.objects.selected = collision_object
file_name = os.path.join(tempfile.gettempdir(), "model{0}.stl".format(str(file_number)))
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
bpy.ops.transform.resize(value=(OCL_SCALE, OCL_SCALE, OCL_SCALE), constraint_axis=(False, False, False),
orient_type='GLOBAL', mirror=False, use_proportional_edit=False,
proportional_edit_falloff='SMOOTH', proportional_size=1, snap=False,
snap_target='CLOSEST', snap_point=(0, 0, 0), snap_align=False, snap_normal=(0, 0, 0),
texture_space=False, release_confirm=False)
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
bpy.ops.export_mesh.stl(check_existing=True, filepath=file_name, filter_glob="*.stl", use_selection=True,
ascii=False, use_mesh_modifiers=True, axis_forward='Y', axis_up='Z', global_scale=1.0)
bpy.ops.object.delete()
file_number += 1
async def oclSamplePoints(operation, points):
samples = await ocl_sample(operation, points)
pointSamplesFromOCL(points, samples)
async def oclSample(operation, chunks):
samples = await ocl_sample(operation, chunks)
chunkPointSamplesFromOCL(chunks, samples)
async def oclResampleChunks(operation, chunks_to_resample,use_cached_mesh):
tmp_chunks = list()
tmp_chunks.append(camPathChunk(inpoints=[]))
for chunk, i_start, i_length in chunks_to_resample:
for p_index in range(i_start, i_start + i_length):
tmp_chunks[0].append(chunk.points[p_index])
samples = await ocl_sample(operation, tmp_chunks,use_cached_mesh=use_cached_mesh)
sample_index = 0
for chunk, i_start, i_length in chunks_to_resample:
z = np.array(p.z for p in samples[sample_index:sample_index+i_length]) / OCL_SCALE
chunk.setZ(z,if_bigger=True)
# sample_index += i_length
# for p_index in range(i_start, i_start + i_length):
# z = samples[sample_index].z / OCL_SCALE
# sample_index += 1
# if z > chunk.points[p_index][2]:
# chunk.points[p_index][2] = z
def oclWaterlineLayerHeights(operation):
layers = []
l_last = operation.minz
l_step = operation.stepdown
l_first = operation.maxz - l_step
l_depth = l_first
while l_depth > (l_last + 0.0000001):
layers.append(l_depth)
l_depth -= l_step
layers.append(l_last)
return layers
def oclGetMedialAxis(operation, chunks):
oclWaterlineHeightsToOCL(operation)
operationSettingsToOCL(operation)
curvesToOCL(operation)
call([PYTHON_BIN, os.path.join(bpy.utils.script_path_pref(), "addons", "cam", "opencamlib", "ocl.py")])
waterlineChunksFromOCL(operation, chunks)
async def oclGetWaterline(operation, chunks):
layers = oclWaterlineLayerHeights(operation)
oclSTL = get_oclSTL(operation)
op_cutter_type = operation.cutter_type
op_cutter_diameter = operation.cutter_diameter
op_minz = operation.minz
if op_cutter_type == "VCARVE":
op_cutter_tip_angle = operation['cutter_tip_angle']
cutter = None
cutter_length = 150 #TODO: automatically determine necessary cutter length depending on object size
if op_cutter_type == 'END':
cutter = ocl.CylCutter((op_cutter_diameter + operation.skin * 2) * 1000, cutter_length)
elif op_cutter_type == 'BALLNOSE':
cutter = ocl.BallCutter((op_cutter_diameter + operation.skin * 2) * 1000, cutter_length)
elif op_cutter_type == 'VCARVE':
cutter = ocl.ConeCutter((op_cutter_diameter + operation.skin * 2) * 1000, op_cutter_tip_angle, cutter_length)
else:
print("Cutter unsupported: {0}\n".format(op_cutter_type))
quit()
waterline = ocl.Waterline()
waterline.setSTL(oclSTL)
waterline.setCutter(cutter)
waterline.setSampling(0.1)#TODO: add sampling setting to UI
last_pos=[0,0,0]
for count,height in enumerate(layers):
layer_chunks=[]
await progress_async("Waterline",int((100*count)/len(layers)))
waterline.reset()
waterline.setZ(height * OCL_SCALE)
waterline.run2()
wl_loops = waterline.getLoops()
for l in wl_loops:
inpoints=[]
for p in l:
inpoints.append((p.x / OCL_SCALE, p.y / OCL_SCALE, p.z / OCL_SCALE))
inpoints.append(inpoints[0])
chunk=camPathChunk(inpoints=inpoints)
chunk.closed = True
layer_chunks.append(chunk)
# sort chunks so that ordering is stable
chunks.extend(await utils.sortChunks(layer_chunks,operation,last_pos=last_pos))
if len(chunks)>0:
last_pos=chunks[-1].get_point(-1)
# def oclFillMedialAxis(operation):