kopia lustrzana https://github.com/vilemduha/blendercam
				
				
				
			
		
			
				
	
	
		
			241 wiersze
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			241 wiersze
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
| # blender CAM simple.py (c) 2012 Vilem Novak
 | |
| #
 | |
| # ***** BEGIN GPL LICENSE BLOCK *****
 | |
| #
 | |
| #
 | |
| # This program is free software; you can redistribute it and/or
 | |
| # modify it under the terms of the GNU General Public License
 | |
| # as published by the Free Software Foundation; either version 2
 | |
| # of the License, or (at your option) any later version.
 | |
| #
 | |
| # This program is distributed in the hope that it will be useful,
 | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
 | |
| # GNU General Public License for more details.
 | |
| #
 | |
| # You should have received a copy of the GNU General Public License
 | |
| # along with this program; if not, write to the Free Software Foundation,
 | |
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | |
| #
 | |
| # ***** END GPL LICENCE BLOCK *****
 | |
| 
 | |
| import math, sys, os, string
 | |
| import time
 | |
| import bpy
 | |
| import mathutils
 | |
| from mathutils import *
 | |
| from math import *
 | |
| 
 | |
| 
 | |
| def tuple_add(t, t1):  # add two tuples as Vectors
 | |
|     return (t[0] + t1[0], t[1] + t1[1], t[2] + t1[2])
 | |
| 
 | |
| 
 | |
| def tuple_sub(t, t1):  # sub two tuples as Vectors
 | |
|     return (t[0] - t1[0], t[1] - t1[1], t[2] - t1[2])
 | |
| 
 | |
| 
 | |
| def tuple_mul(t, c):  # multiply two tuples with a number
 | |
|     return (t[0] * c, t[1] * c, t[2] * c)
 | |
| 
 | |
| 
 | |
| def tuple_length(t):  # get length of vector, but passed in as tuple.
 | |
|     return (Vector(t).length)
 | |
| 
 | |
| 
 | |
| # timing functions for optimisation purposes...
 | |
| def timinginit():
 | |
|     return [0, 0]
 | |
| 
 | |
| 
 | |
| def timingstart(tinf):
 | |
|     t = time.time()
 | |
|     tinf[1] = t
 | |
| 
 | |
| 
 | |
| def timingadd(tinf):
 | |
|     t = time.time()
 | |
|     tinf[0] += t - tinf[1]
 | |
| 
 | |
| 
 | |
| def timingprint(tinf):
 | |
|     print('time ' + str(tinf[0]) + 'seconds')
 | |
| 
 | |
| 
 | |
| def progress(text, n=None):
 | |
|     """function for reporting during the script, works for background operations in the header."""
 | |
|     # for i in range(n+1):
 | |
|     # sys.stdout.flush()
 | |
|     text = str(text)
 | |
|     if n == None:
 | |
|         n = ''
 | |
|     else:
 | |
|         n = ' ' + str(int(n * 1000) / 1000) + '%'
 | |
|     # d=int(n/2)
 | |
|     spaces = ' ' * (len(text) + 55)
 | |
|     sys.stdout.write('progress{%s%s}\n' % (text, n))
 | |
|     sys.stdout.flush()
 | |
| 
 | |
| 
 | |
| # bpy.data.window_managers['WinMan'].progress_update(n)
 | |
| # if bpy.context.scene.o
 | |
| # bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
 | |
| # time.sleep(0.5)
 | |
| 
 | |
| #
 | |
| def activate(o):
 | |
|     """makes an object active, used many times in blender"""
 | |
|     s = bpy.context.scene
 | |
|     bpy.ops.object.select_all(action='DESELECT')
 | |
|     o.select_set(state=True)
 | |
|     s.objects[o.name].select_set(state=True)
 | |
|     bpy.context.view_layer.objects.active = o
 | |
| 
 | |
| 
 | |
| def dist2d(v1, v2):
 | |
|     """distance between two points in 2d"""
 | |
|     return math.hypot((v1[0] - v2[0]), (v1[1] - v2[1]))
 | |
| 
 | |
| 
 | |
| def delob(ob):
 | |
|     """object deletion for multiple uses"""
 | |
|     activate(ob)
 | |
|     bpy.ops.object.delete(use_global=False)
 | |
| 
 | |
| 
 | |
| def dupliob(o, pos):
 | |
|     """helper function for visualising cutter positions in bullet simulation"""
 | |
|     activate(o)
 | |
|     bpy.ops.object.duplicate()
 | |
|     s = 1.0 / BULLET_SCALE
 | |
|     bpy.ops.transform.resize(value=(s, s, s), constraint_axis=(False, False, False), orient_type='GLOBAL',
 | |
|                              mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH',
 | |
|                              proportional_size=1)
 | |
|     o = bpy.context.active_object
 | |
|     bpy.ops.rigidbody.object_remove()
 | |
|     o.location = pos
 | |
| 
 | |
| 
 | |
| def addToGroup(ob, groupname):
 | |
|     activate(ob)
 | |
|     if bpy.data.groups.get(groupname) == None:
 | |
|         bpy.ops.group.create(name=groupname)
 | |
|     else:
 | |
|         bpy.ops.object.group_link(group=groupname)
 | |
| 
 | |
| 
 | |
| def compare(v1, v2, vmiddle, e):
 | |
|     """comparison for optimisation of paths"""
 | |
|     # e=0.0001
 | |
|     v1 = Vector(v1)
 | |
|     v2 = Vector(v2)
 | |
|     vmiddle = Vector(vmiddle)
 | |
|     vect1 = v2 - v1
 | |
|     vect2 = vmiddle - v1
 | |
|     vect1.normalize()
 | |
|     vect1 *= vect2.length
 | |
|     v = vect2 - vect1
 | |
|     if v.length < e:
 | |
|         return True
 | |
|     return False
 | |
| 
 | |
| 
 | |
| def isVerticalLimit(v1, v2, limit):
 | |
|     """test path segment on verticality threshold, for protect_vertical option"""
 | |
|     z = abs(v1[2] - v2[2])
 | |
|     # verticality=0.05
 | |
|     # this will be better.
 | |
|     #
 | |
|     # print(a)
 | |
|     if z > 0:
 | |
|         v2d = Vector((0, 0, -1))
 | |
|         v3d = Vector((v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]))
 | |
|         a = v3d.angle(v2d)
 | |
|         if a > pi / 2:
 | |
|             a = abs(a - pi)
 | |
|         # print(a)
 | |
|         if a < limit:
 | |
|             # print(abs(v1[0]-v2[0])/z)
 | |
|             # print(abs(v1[1]-v2[1])/z)
 | |
|             if v1[2] > v2[2]:
 | |
|                 v1 = (v2[0], v2[1], v1[2])
 | |
|                 return v1, v2
 | |
|             else:
 | |
|                 v2 = (v1[0], v1[1], v2[2])
 | |
|                 return v1, v2
 | |
|     return v1, v2
 | |
| 
 | |
| 
 | |
| def getCachePath(o):
 | |
|     fn = bpy.data.filepath
 | |
|     l = len(bpy.path.basename(fn))
 | |
|     bn = bpy.path.basename(fn)[:-6]
 | |
|     print('fn-l:',fn[:-l])
 | |
|     print('bn:',bn)
 | |
| 
 | |
|     iname = fn[:-l] + 'temp_cam' + os.sep + bn + '_' + o.name
 | |
|     return iname
 | |
| 
 | |
| def getSimulationPath():
 | |
|     fn = bpy.data.filepath
 | |
|     l = len(bpy.path.basename(fn))
 | |
|     iname = fn[:-l] + 'temp_cam' + os.sep
 | |
|     return iname
 | |
| 
 | |
| def safeFileName(name):  # for export gcode
 | |
|     valid_chars = "-_.()%s%s" % (string.ascii_letters, string.digits)
 | |
|     filename = ''.join(c for c in name if c in valid_chars)
 | |
|     return filename
 | |
| 
 | |
| 
 | |
| def strInUnits(x, precision=5):
 | |
|     if bpy.context.scene.unit_settings.system == 'METRIC':
 | |
|         return str(round(x * 1000, precision)) + ' mm '
 | |
|     elif bpy.context.scene.unit_settings.system == 'IMPERIAL':
 | |
|         return str(round(x * 1000 / 25.4, precision)) + "'' "
 | |
|     else:
 | |
|         return str(x)
 | |
| 
 | |
| # join multiple objects starting with 'name' renaming final object as 'name'
 | |
| def joinMultiple(name):
 | |
|     scene = bpy.context.scene
 | |
|     for ob in scene.objects:  # join pocket curve calculations
 | |
|         if ob.name.startswith(name):
 | |
|             ob.select_set(True)
 | |
|         else:
 | |
|             ob.select_set(False)
 | |
|     bpy.ops.object.join()
 | |
|     bpy.context.active_object.name = name  # rename object
 | |
| 
 | |
| def selectMultiple(name):
 | |
|     scene = bpy.context.scene
 | |
|     for ob in scene.objects:  # join pocket curve calculations
 | |
|         if ob.name.startswith(name):
 | |
|             ob.select_set(True)
 | |
|         else:
 | |
|             ob.select_set(False)
 | |
| 
 | |
| # remove multiple objects starting with 'name'.... useful for fixed name operation
 | |
| def removeMultiple(name):
 | |
|     scene = bpy.context.scene
 | |
|     bpy.ops.object.select_all(action='DESELECT')
 | |
|     for ob in scene.objects:
 | |
|         if ob.name.startswith(name):
 | |
|             ob.select_set(True)
 | |
|             bpy.ops.object.delete()
 | |
| 
 | |
| 
 | |
| def makeActive(name):
 | |
|     bpy.ops.object.select_all(action='DESELECT')
 | |
|     ob = bpy.context.scene.objects[name]
 | |
|     bpy.ops.object.select_all(action='DESELECT')
 | |
|     bpy.context.view_layer.objects.active = ob  # Make the cube the active object
 | |
|     ob.select_set(True)
 | |
| 
 | |
| 
 | |
| def activeName(name):
 | |
|     bpy.context.active_object.name = name
 | |
| 
 | |
| def rename(name,name2):
 | |
|     makeActive(name)
 | |
|     bpy.context.active_object.name = name2 |