kopia lustrzana https://github.com/vilemduha/blendercam
199 wiersze
7.1 KiB
Python
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):
|