kopia lustrzana https://github.com/vilemduha/blendercam
				
				
				
			Merge pull request #13 from vilemnovak/revert-12-revert-10-master
Revert "Revert "- little bug fixes and some code refactoring""pull/25/head
						commit
						85809b9611
					
				|  | @ -16,4 +16,4 @@ config/bookmarks.txt | |||
| *.py | ||||
| config/recent-files.txt | ||||
| scripts/addons_contrib/add_mesh_rocks/add_mesh_rocks.xml | ||||
| scripts/addons_contrib/online_mat_lib/material-library/bundled/cycles/wood/rough_pine.bcm | ||||
| scripts/addons_contrib/online_mat_lib/material-library/bundled/cycles/wood/rough_pine.bcm | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ from bpy.types import Menu, Operator, UIList, AddonPreferences | |||
| 
 | ||||
| #from . import patterns | ||||
| #from . import chunk_operations | ||||
| from cam import ui, ops,utils, simple,polygon_utils_cam#, post_processors | ||||
| from cam import ui, ops, utils, simple, polygon_utils_cam#, post_processors | ||||
| import numpy | ||||
| import Polygon | ||||
| from bpy.app.handlers import persistent | ||||
|  | @ -85,7 +85,7 @@ class machineSettings(bpy.types.PropertyGroup): | |||
| 	'''stores all data for machines''' | ||||
| 	#name = bpy.props.StringProperty(name="Machine Name", default="Machine") | ||||
| 	post_processor = EnumProperty(name='Post processor', | ||||
| 		items=(('ISO','Iso','this should export a standardized gcode'),('MACH3','Mach3','default mach3'),('EMC','EMC - LinuxCNC','default emc'),('HEIDENHAIN','Heidenhain','heidenhain'),('TNC151','Heidenhain TNC151','Post Processor for the Heidenhain TNC151 machine'),('SIEGKX1','Sieg KX1','Sieg KX1'),('HM50','Hafco HM-50','Hafco HM-50'),('CENTROID','Centroid M40','Centroid M40'),('ANILAM','Anilam Crusader M','Anilam Crusader M'),('GRAVOS','Gravos','Gravos'),('WIN-PC','Win-PC','German CNC'),('SHOPBOT MTC','ShopBot MTC','ShopBot MTC'),('LYNX_OTTER_O','Lynx Otter o','Lynx Otter o')), | ||||
| 		items=(('ISO','Iso','this should export a standardized gcode'),('MACH3','Mach3','default mach3'),('EMC','EMC - LinuxCNC','default emc'),('GRBL','grbl','grbl on Arduino cnc shield'),('HEIDENHAIN','Heidenhain','heidenhain'),('TNC151','Heidenhain TNC151','Post Processor for the Heidenhain TNC151 machine'),('SIEGKX1','Sieg KX1','Sieg KX1'),('HM50','Hafco HM-50','Hafco HM-50'),('CENTROID','Centroid M40','Centroid M40'),('ANILAM','Anilam Crusader M','Anilam Crusader M'),('GRAVOS','Gravos','Gravos'),('WIN-PC','Win-PC','German CNC'),('SHOPBOT MTC','ShopBot MTC','ShopBot MTC'),('LYNX_OTTER_O','Lynx Otter o','Lynx Otter o')), | ||||
| 		description='Post processor', | ||||
| 		default='MACH3') | ||||
| 	#units = EnumProperty(name='Units', items = (('IMPERIAL', '')) | ||||
|  | @ -447,7 +447,7 @@ class camOperation(bpy.types.PropertyGroup): | |||
| 	plunge_angle =	bpy.props.FloatProperty(name="Plunge angle", description="What angle is allready considered to plunge", default=math.pi/6, min=0, max=math.pi*0.5 , precision=0, subtype="ANGLE" , unit="ROTATION" , update = updateRest) | ||||
| 	spindle_rpm = FloatProperty(name="Spindle rpm", description="Spindle speed ", min=1000, max=60000, default=12000, update = updateChipload) | ||||
| 	#movement parallel_step_back  | ||||
| 	movement_type = EnumProperty(name='Movement type',items=(('CONVENTIONAL','Conventional', 'a'),('CLIMB', 'Climb', 'a'),('MEANDER', 'Meander' , 'a')	 ),description='movement type', default='CLIMB', update = updateRest) | ||||
| 	movement_type = EnumProperty(name='Movement type',items=(('CONVENTIONAL','Conventional / Up milling', 'cutter rotates against the direction of the feed'),('CLIMB', 'Climb / Down milling', 'cutter rotates with the direction of the feed'),('MEANDER', 'Meander / Zig Zag' , 'cutting is done both with and against the rotation of the spindle')	 ),description='movement type', default='CLIMB', update = updateRest) | ||||
| 	spindle_rotation_direction = EnumProperty(name='Spindle rotation', items=(('CW','Clock wise', 'a'),('CCW', 'Counter clock wise', 'a')),description='Spindle rotation direction',default='CW', update = updateRest) | ||||
| 	free_movement_height = bpy.props.FloatProperty(name="Free movement height", default=0.01, min=0.0000, max=32,precision=PRECISION, unit="LENGTH", update = updateRest) | ||||
| 	movement_insideout = EnumProperty(name='Direction', items=(('INSIDEOUT','Inside out', 'a'),('OUTSIDEIN', 'Outside in', 'a')),description='approach to the piece',default='INSIDEOUT', update = updateRest) | ||||
|  |  | |||
|  | @ -0,0 +1,287 @@ | |||
| from . import nc | ||||
| from . import iso_modal | ||||
| import math | ||||
| import datetime | ||||
| import time | ||||
| 
 | ||||
| now = datetime.datetime.now() | ||||
| 
 | ||||
| class Creator(iso_modal.Creator): | ||||
|     def __init__(self): | ||||
|         iso_modal.Creator.__init__(self) | ||||
|         self.absolute_flag = True | ||||
|         self.prev_g91 = '' | ||||
|         self.useCrc = False | ||||
|         self.start_of_line = True | ||||
| 
 | ||||
|     def write_blocknum(self): | ||||
|         self.start_of_line = True | ||||
|          | ||||
|     def SPACE(self): | ||||
|         if self.start_of_line == True: | ||||
|             self.start_of_line = False | ||||
|             return '' | ||||
|         else: | ||||
|             return ' ' | ||||
|          | ||||
|     def PROGRAM_END(self): return ' ' | ||||
|          | ||||
| ############################################################################ | ||||
| ## Begin Program  | ||||
| 
 | ||||
| 
 | ||||
|     def program_begin(self, id, comment): | ||||
|         if (self.useCrc == False): | ||||
|             self.write( ('(Created with grbl post processor ' + str(now.strftime("%Y/%m/%d %H:%M")) + ')' + '\n') ) | ||||
|         else:   | ||||
|             self.write( ('(Created with grbl Cutter Radius Compensation post processor ' + str(now.strftime("%Y/%m/%d %H:%M")) + ')' + '\n') ) | ||||
| 
 | ||||
| 	 | ||||
| 
 | ||||
| 
 | ||||
| ############################################################################ | ||||
| ##  Settings | ||||
| 
 | ||||
|     def tool_defn(self, id, name='', radius=None, length=None, gradient=None): | ||||
|         pass | ||||
| 
 | ||||
|     def tool_change(self, id): | ||||
|         pass | ||||
| 		 | ||||
|     def comment(self, text): | ||||
|         self.write_blocknum() | ||||
|         self.write((self.COMMENT(text) + '\n')) | ||||
| 
 | ||||
| # This is the coordinate system we're using.  G54->G59, G59.1, G59.2, G59.3 | ||||
| # These are selected by values from 1 to 9 inclusive. | ||||
|     def workplane(self, id): | ||||
|         if ((id >= 1) and (id <= 6)): | ||||
|             self.write_blocknum() | ||||
|             self.write( (self.WORKPLANE() % (id + self.WORKPLANE_BASE())) + '\t (Select Relative Coordinate System)\n') | ||||
|         if ((id >= 7) and (id <= 9)): | ||||
|             self.write_blocknum() | ||||
|             self.write( ((self.WORKPLANE() % (6 + self.WORKPLANE_BASE())) + ('.%i' % (id - 6))) + '\t (Select Relative Coordinate System)\n') | ||||
| 
 | ||||
| 
 | ||||
| ############################################################################ | ||||
| ##  Moves | ||||
| 
 | ||||
| 
 | ||||
| ############################################################################ | ||||
| ## Probe routines | ||||
|     def report_probe_results(self, x1=None, y1=None, z1=None, x2=None, y2=None, z2=None, x3=None, y3=None, z3=None, x4=None, y4=None, z4=None, x5=None, y5=None, z5=None, x6=None, y6=None, z6=None, xml_file_name=None ): | ||||
|         if (xml_file_name != None): | ||||
|             self.comment('Generate an XML document describing the probed coordinates found'); | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOGOPEN,') | ||||
|             self.write(xml_file_name) | ||||
|             self.write(')\n') | ||||
| 
 | ||||
|         self.write_blocknum() | ||||
|         self.write('(LOG,<POINTS>)\n') | ||||
| 
 | ||||
|         if ((x1 != None) or (y1 != None) or (z1 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<POINT>)\n') | ||||
| 
 | ||||
|         if (x1 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + x1 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<X>#<_value></X>)\n') | ||||
| 
 | ||||
|         if (y1 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + y1 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Y>#<_value></Y>)\n') | ||||
| 
 | ||||
|         if (z1 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + z1 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Z>#<_value></Z>)\n') | ||||
| 
 | ||||
|         if ((x1 != None) or (y1 != None) or (z1 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,</POINT>)\n') | ||||
| 
 | ||||
|         if ((x2 != None) or (y2 != None) or (z2 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<POINT>)\n') | ||||
| 
 | ||||
|         if (x2 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + x2 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<X>#<_value></X>)\n') | ||||
| 
 | ||||
|         if (y2 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + y2 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Y>#<_value></Y>)\n') | ||||
| 
 | ||||
|         if (z2 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + z2 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Z>#<_value></Z>)\n') | ||||
| 
 | ||||
|         if ((x2 != None) or (y2 != None) or (z2 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,</POINT>)\n') | ||||
| 
 | ||||
|         if ((x3 != None) or (y3 != None) or (z3 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<POINT>)\n') | ||||
| 
 | ||||
|         if (x3 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + x3 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<X>#<_value></X>)\n') | ||||
| 
 | ||||
|         if (y3 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + y3 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Y>#<_value></Y>)\n') | ||||
| 
 | ||||
|         if (z3 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + z3 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Z>#<_value></Z>)\n') | ||||
| 
 | ||||
|         if ((x3 != None) or (y3 != None) or (z3 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,</POINT>)\n') | ||||
| 
 | ||||
|         if ((x4 != None) or (y4 != None) or (z4 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<POINT>)\n') | ||||
| 
 | ||||
|         if (x4 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + x4 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<X>#<_value></X>)\n') | ||||
| 
 | ||||
|         if (y4 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + y4 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Y>#<_value></Y>)\n') | ||||
| 
 | ||||
|         if (z4 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + z4 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Z>#<_value></Z>)\n') | ||||
| 
 | ||||
|         if ((x4 != None) or (y4 != None) or (z4 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,</POINT>)\n') | ||||
| 
 | ||||
|         if ((x5 != None) or (y5 != None) or (z5 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<POINT>)\n') | ||||
| 
 | ||||
|         if (x5 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + x5 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<X>#<_value></X>)\n') | ||||
| 
 | ||||
|         if (y5 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + y5 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Y>#<_value></Y>)\n') | ||||
| 
 | ||||
|         if (z5 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + z5 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Z>#<_value></Z>)\n') | ||||
| 
 | ||||
|         if ((x5 != None) or (y5 != None) or (z5 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,</POINT>)\n') | ||||
| 
 | ||||
|         if ((x6 != None) or (y6 != None) or (z6 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<POINT>)\n') | ||||
| 
 | ||||
|         if (x6 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + x6 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<X>#<_value></X>)\n') | ||||
| 
 | ||||
|         if (y6 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + y6 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Y>#<_value></Y>)\n') | ||||
| 
 | ||||
|         if (z6 != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + z6 + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Z>#<_value></Z>)\n') | ||||
| 
 | ||||
|         if ((x6 != None) or (y6 != None) or (z6 != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,</POINT>)\n') | ||||
| 
 | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,</POINTS>)\n') | ||||
| 
 | ||||
|         if (xml_file_name != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOGCLOSE)\n') | ||||
| 
 | ||||
|     def open_log_file(self, xml_file_name=None ): | ||||
|         self.write_blocknum() | ||||
|         self.write('(LOGOPEN,') | ||||
|         self.write(xml_file_name) | ||||
|         self.write(')\n') | ||||
| 
 | ||||
|     def close_log_file(self): | ||||
|         self.write_blocknum() | ||||
|         self.write('(LOGCLOSE)\n') | ||||
| 
 | ||||
|     def log_coordinate(self, x=None, y=None, z=None): | ||||
|         if ((x != None) or (y != None) or (z != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<POINT>)\n') | ||||
| 
 | ||||
|         if (x != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + x + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<X>#<_value></X>)\n') | ||||
| 
 | ||||
|         if (y != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + y + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Y>#<_value></Y>)\n') | ||||
| 
 | ||||
|         if (z != None): | ||||
|             self.write_blocknum() | ||||
|             self.write('#<_value>=[' + z + ']\n') | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,<Z>#<_value></Z>)\n') | ||||
| 
 | ||||
|         if ((x != None) or (y != None) or (z != None)): | ||||
|             self.write_blocknum() | ||||
|             self.write('(LOG,</POINT>)\n') | ||||
| 
 | ||||
|     def log_message(self, message=None ): | ||||
|         self.write_blocknum() | ||||
|         self.write('(LOG,' + message + ')\n') | ||||
| 
 | ||||
| nc.creator = Creator() | ||||
|  | @ -381,6 +381,7 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, bpy.types.Panel): | |||
| 						layout.prop(ao,'strategy') | ||||
| 					layout.prop(ao,'rotary_axis_1') | ||||
| 					layout.prop(ao,'rotary_axis_2') | ||||
| 
 | ||||
| 				if ao.strategy=='BLOCK' or ao.strategy=='SPIRAL' or ao.strategy=='CIRCLES' or ao.strategy=='OUTLINEFILL': | ||||
| 					layout.prop(ao,'movement_insideout') | ||||
| 					 | ||||
|  | @ -423,7 +424,6 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, bpy.types.Panel): | |||
| 					if ao.waterline_fill: | ||||
| 						layout.prop(ao,'dist_between_paths')			 | ||||
| 						layout.prop(ao,'waterline_project') | ||||
| 					layout.prop(ao,'skin') | ||||
| 					layout.prop(ao,'inverse') | ||||
| 				elif ao.strategy=='CARVE': | ||||
| 					layout.prop(ao,'carve_depth') | ||||
|  | @ -449,9 +449,7 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, bpy.types.Panel): | |||
| 					layout.prop(ao,'dist_along_paths') | ||||
| 					if ao.strategy=='PARALLEL' or ao.strategy=='CROSS': | ||||
| 						layout.prop(ao,'parallel_angle') | ||||
| 						 | ||||
| 						 | ||||
| 					layout.prop(ao,'skin') | ||||
| 												 | ||||
| 					layout.prop(ao,'inverse') | ||||
| 				#elif ao.strategy=='SLICES': | ||||
| 				#	layout.prop(ao,'slice_detail')	 | ||||
|  | @ -459,6 +457,8 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, bpy.types.Panel): | |||
| 			#layout.operator("object.cam_pack_objects") | ||||
| 			#layout.operator("scene.cam_orientation_add") | ||||
| 			#gname=ao.name+'_orientations' | ||||
| 
 | ||||
| 			layout.prop(ao,'skin') | ||||
| 			 | ||||
| 			#if gname in bpy.data.groups: | ||||
| 			#	layout.label('orientations') | ||||
|  | @ -576,7 +576,7 @@ class CAM_OPTIMISATION_Panel(CAMButtonsPanel, bpy.types.Panel): | |||
| 				if ao.optimize: | ||||
| 					layout.prop(ao,'optimize_threshold') | ||||
| 				if ao.geometry_source=='OBJECT' or ao.geometry_source=='GROUP': | ||||
| 					exclude_exact= ao.strategy=='CUTOUT' or ao.strategy=='DRILL' or ao.strategy=='PENCIL' | ||||
| 					exclude_exact= ao.strategy=='WATERLINE' or ao.strategy=='POCKET' or ao.strategy=='CUTOUT' or ao.strategy=='DRILL' or ao.strategy=='PENCIL' | ||||
| 					if not exclude_exact: | ||||
| 						layout.prop(ao,'use_exact') | ||||
| 						if ao.use_exact: | ||||
|  |  | |||
|  | @ -1060,6 +1060,9 @@ def exportGcodePath(filename,vertslist,operations): | |||
| 	elif m.post_processor=='EMC': | ||||
| 		extension = '.ngc' | ||||
| 		from .nc import emc2b as postprocessor | ||||
| 	elif m.post_processor=='GRBL': | ||||
| 		extension = '.ngc' | ||||
| 		from .nc import grbl as postprocessor | ||||
| 	elif m.post_processor=='HM50': | ||||
| 		from .nc import hm50 as postprocessor | ||||
| 	elif m.post_processor=='HEIDENHAIN': | ||||
|  | @ -1561,15 +1564,28 @@ def sortChunks(chunks,o): | |||
| 				ch = getClosest(o,pos,chunks) | ||||
| 			#	break | ||||
| 			#pass; | ||||
| 		if ch!=None:#found next chunk, append it to list | ||||
| 			ch.sorted=True | ||||
| 			ch.adaptdist(pos,o) | ||||
| 		if ch is not None:#found next chunk, append it to list | ||||
| 			ch.sorted = True | ||||
| 			ch.adaptdist(pos, o) | ||||
| 			print(ch) | ||||
| 			chunks.remove(ch) | ||||
| 			sortedchunks.append(ch) | ||||
| 			lastch=ch | ||||
| 			pos=lastch.points[-1] | ||||
| 		i-=1	 | ||||
| 			lastch = ch | ||||
| 			pos = lastch.points[-1] | ||||
| 		# experimental fix for infinite loop problem | ||||
| 		#else: | ||||
| 			# can't find chunks close enough and still some chunks left | ||||
| 			# to be sorted. For now just move the remaining chunks over to  | ||||
| 			# the sorted list. | ||||
| 			# This fixes an infinite loop condition that occurs sometimes. | ||||
| 			# This is a bandaid fix: need to find the root cause of this problem | ||||
| 			# suspect it has to do with the sorted flag? | ||||
| 			#print("no chunks found closest. Chunks not sorted: ", len(chunks)) | ||||
| 			#sortedchunks.extend(chunks) | ||||
| 			#chunks[:] = [] | ||||
| 			 | ||||
| 		i -= 1 | ||||
| 			 | ||||
| 		''' | ||||
| 		if i<-200: | ||||
| 			for ch in chunks: | ||||
|  | @ -2284,236 +2300,239 @@ def addBridges(ch,o): | |||
| 				ch.points[p[0]]=p[1] | ||||
| 			for pi in range(len(insertpoints)-1,-1,-1): | ||||
| 				ch.points.insert(insertpoints[pi][0],insertpoints[pi][1]) | ||||
| #this is the main function. | ||||
| #FIXME: split strategies into separate file! | ||||
| #def cutoutStrategy(o): | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| ###########cutout strategy is completely here: | ||||
| def strategy_cutout( o ): | ||||
| 	#ob=bpy.context.active_object | ||||
| 	print('operation: cutout') | ||||
| 	offset=True | ||||
| 	if o.cut_type=='ONLINE' and o.onlycurves==True:#is separate to allow open curves :) | ||||
| 		print('separate') | ||||
| 		chunksFromCurve=[] | ||||
| 		for ob in o.objects: | ||||
| 			chunksFromCurve.extend(curveToChunks(ob)) | ||||
| 		#p=Polygon.Polygon()	 | ||||
| 		for ch in chunksFromCurve: | ||||
| 			#print(ch.points) | ||||
| 			 | ||||
| 			if len(ch.points)>2: | ||||
| 				ch.poly=chunkToShapely(ch) | ||||
| 				#p.addContour(ch.poly) | ||||
| 	else: | ||||
| 		chunksFromCurve=[] | ||||
| 		if o.cut_type=='ONLINE': | ||||
| 			p=getObjectOutline(0,o,True) | ||||
| 			 | ||||
| 		else: | ||||
| 			offset=True | ||||
| 			if o.cut_type=='INSIDE': | ||||
| 				offset=False | ||||
| 				 | ||||
| 			p=getObjectOutline(o.cutter_diameter/2,o,offset) | ||||
| 			if o.outlines_count>1: | ||||
| 				for i in range(1,o.outlines_count): | ||||
| 					chunksFromCurve.extend(shapelyToChunks(p,-1)) | ||||
| 					p = p.buffer(distance = o.dist_between_paths * offset, resolution = o.circle_detail) | ||||
| 			 | ||||
| 				 | ||||
| 		chunksFromCurve.extend(shapelyToChunks(p,-1)) | ||||
| 		if o.outlines_count>1 and o.movement_insideout=='OUTSIDEIN': | ||||
| 			chunksFromCurve.reverse() | ||||
| 			 | ||||
| 	#parentChildPoly(chunksFromCurve,chunksFromCurve,o) | ||||
| 	chunksFromCurve=limitChunks(chunksFromCurve,o) | ||||
| 	parentChildPoly(chunksFromCurve,chunksFromCurve,o) | ||||
| 	if o.outlines_count==1: | ||||
| 		chunksFromCurve=sortChunks(chunksFromCurve,o) | ||||
| 	 | ||||
| 	#if o.outlines_count>0 and o.cut_type!='ONLINE' and o.movement_insideout=='OUTSIDEIN':#reversing just with more outlines | ||||
| 	#	chunksFromCurve.reverse() | ||||
| 					 | ||||
| 	if (o.movement_type=='CLIMB' and o.spindle_rotation_direction=='CCW') or (o.movement_type=='CONVENTIONAL' and o.spindle_rotation_direction=='CW'): | ||||
| 		for ch in chunksFromCurve: | ||||
| 			ch.points.reverse() | ||||
| 		 | ||||
| 	if o.cut_type=='INSIDE':#there would bee too many conditions above, so for now it gets reversed once again when inside cutting. | ||||
| 		for ch in chunksFromCurve: | ||||
| 			ch.points.reverse() | ||||
| 			 | ||||
| 	 | ||||
| 	if o.use_layers: | ||||
| 		layers=[] | ||||
| 		n=math.ceil((o.maxz-o.min.z)/o.stepdown) | ||||
| 		layerstart=o.maxz | ||||
| 		for x in range(0,n): | ||||
| 			layerend=max(o.maxz-((x+1)*o.stepdown),o.min.z) | ||||
| 			if int(layerstart*10**8)!=int(layerend*10**8):#it was possible that with precise same end of operation, last layer was done 2x on exactly same level... | ||||
| 				layers.append([layerstart,layerend]) | ||||
| 			layerstart=layerend | ||||
| 	else: | ||||
| 			layers=[[o.maxz,o.min.z]] | ||||
| 		 | ||||
| 	print(layers) | ||||
| 	 | ||||
| 	extendorder=[] | ||||
| 	if o.first_down:#each shape gets either cut all the way to bottom, or every shape gets cut 1 layer, then all again. has to create copies, because same chunks are worked with on more layers usually | ||||
| 		for chunk in chunksFromCurve: | ||||
| 			for layer in layers: | ||||
| 				extendorder.append([chunk.copy(),layer]) | ||||
| 	else: | ||||
| 		for layer in layers: | ||||
| 			for chunk in chunksFromCurve: | ||||
| 				extendorder.append([chunk.copy(),layer]) | ||||
| 	 | ||||
| 	for chl in extendorder:#Set Z for all chunks | ||||
| 		chunk=chl[0] | ||||
| 		layer=chl[1] | ||||
| 		print(layer[1]) | ||||
| 		chunk.setZ(layer[1]) | ||||
| 	 | ||||
| 	chunks=[] | ||||
| 	 | ||||
| 	if o.ramp:#add ramps or simply add chunks | ||||
| 		for chl in extendorder: | ||||
| 			chunk=chl[0] | ||||
| 			layer=chl[1] | ||||
| 			if chunk.closed: | ||||
| 				chunks.append(chunk.rampContour(layer[0],layer[1],o)) | ||||
| 			else: | ||||
| 				chunks.append(chunk.rampZigZag(layer[0],layer[1],o)) | ||||
| 
 | ||||
| 	if o.use_bridges:#add bridges to chunks | ||||
| 		#bridges=getBridges(p,o) | ||||
| 		bridgeheight=min(0,o.min.z+o.bridges_height) | ||||
| 		for chl in extendorder: | ||||
| 			chunk=chl[0] | ||||
| 			layer=chl[1] | ||||
| 			if layer[1]<bridgeheight: | ||||
| 				addBridges(chunk,o) | ||||
| 
 | ||||
| 	for chl in extendorder: | ||||
| 		chunks.append(chl[0]) | ||||
| 			 | ||||
| 
 | ||||
| 	chunksToMesh(chunks,o) | ||||
| 
 | ||||
| def strategy_curve( o ): | ||||
| 	print('operation: curve') | ||||
| 	pathSamples=[] | ||||
| 	getOperationSources(o) | ||||
| 	if not o.onlycurves: | ||||
| 		o.warnings+= 'at least one of assigned objects is not a curve' | ||||
| 	#ob=bpy.data.objects[o.object_name] | ||||
| 	for ob in o.objects: | ||||
| 		pathSamples.extend(curveToChunks(ob)) | ||||
| 	pathSamples=sortChunks(pathSamples,o)#sort before sampling | ||||
| 	pathSamples=chunksRefine(pathSamples,o) | ||||
| 	 | ||||
| 	if o.ramp: | ||||
| 		for ch in pathSamples: | ||||
| 			nchunk = ch.rampZigZag(ch.zstart, ch.points[0][2],o) | ||||
| 			ch.points=nchunk.points | ||||
| 			 | ||||
| 	chunksToMesh(pathSamples,o) | ||||
| 	 | ||||
| def strategy_proj_curve( s, o ): | ||||
| 	print('operation: projected curve') | ||||
| 	pathSamples = [] | ||||
| 	chunks = [] | ||||
| 	ob = bpy.data.objects[o.curve_object] | ||||
| 	pathSamples.extend(curveToChunks(ob)) | ||||
| 	 | ||||
| 	targetCurve = s.objects[o.curve_object1] | ||||
| 	 | ||||
| 	from cam import chunk | ||||
| 	if targetCurve.type != 'CURVE': | ||||
| 		o.warnings = o.warnings+'Projection target and source have to be curve objects!\n ' | ||||
| 		return | ||||
| 	'''	#mesh method is highly unstable, I don't like itwould be there at all.... better to use curves. | ||||
| 	if targetCurve.type=='MESH': | ||||
| 		 | ||||
| 		c=targetCurve | ||||
| 		for ch in pathSamples: | ||||
| 			ch.depth=0 | ||||
| 			for i,s in enumerate(ch.points): | ||||
| 				np=c.closest_point_on_mesh(s) | ||||
| 				ch.startpoints.append(Vector(s)) | ||||
| 				ch.endpoints.append(np[0]) | ||||
| 				ch.rotations.append((0,0,0)) | ||||
| 				vect = np[0]-Vector(s) | ||||
| 				 | ||||
| 				ch.depth=min(ch.depth,-vect.length) | ||||
| 	else: | ||||
| 	''' | ||||
| 	if 1: | ||||
| 		extend_up = 0.1 | ||||
| 		extend_down = 0.04 | ||||
| 		tsamples = curveToChunks(targetCurve) | ||||
| 		for chi,ch in enumerate(pathSamples): | ||||
| 			cht = tsamples[chi].points | ||||
| 			ch.depth = 0 | ||||
| 			for i,s in enumerate(ch.points): | ||||
| 				#move the points a bit | ||||
| 				ep = Vector(cht[i]) | ||||
| 				sp = Vector(ch.points[i]) | ||||
| 				#extend startpoint | ||||
| 				vecs = sp-ep | ||||
| 				vecs.normalize() | ||||
| 				vecs *= extend_up | ||||
| 				sp += vecs | ||||
| 				ch.startpoints.append(sp) | ||||
| 				 | ||||
| 				#extend endpoint | ||||
| 				vece = sp - ep | ||||
| 				vece.normalize() | ||||
| 				vece *= extend_down | ||||
| 				ep -= vece | ||||
| 				ch.endpoints.append(ep) | ||||
| 						 | ||||
| 				ch.rotations.append((0,0,0)) | ||||
| 				 | ||||
| 				vec = sp - ep | ||||
| 				ch.depth = min(ch.depth,-vec.length) | ||||
| 				ch.points[i] = sp.copy() | ||||
| 			 | ||||
| 			 | ||||
| 	if o.use_layers: | ||||
| 		n = math.ceil(-(ch.depth/o.stepdown)) | ||||
| 		layers = [] | ||||
| 		for x in range(0,n): | ||||
| 			 | ||||
| 			layerstart = -(x*o.stepdown) | ||||
| 			layerend = max(-((x+1)*o.stepdown),ch.depth) | ||||
| 			layers.append([layerstart,layerend]) | ||||
| 	else: | ||||
| 		layerstart = 0# | ||||
| 		layerend = ch.depth# | ||||
| 		layers = [[layerstart,layerend]] | ||||
| 	 | ||||
| 	chunks.extend(sampleChunksNAxis(o,pathSamples,layers)) | ||||
| 	#for ch in pathSamples: | ||||
| 	#	ch.points=ch.endpoints | ||||
| 	chunksToMesh(chunks,o) | ||||
| 
 | ||||
| 	 | ||||
| #this is the main function. | ||||
| #FIXME: split strategies into separate file! | ||||
| #def cutoutStrategy(o): | ||||
| def getPath3axis(context,operation): | ||||
| def getPath3axis(context, operation): | ||||
| 	s=bpy.context.scene | ||||
| 	o=operation | ||||
| 	getBounds(o) | ||||
| 	 | ||||
| 	 | ||||
| 	###########cutout strategy is completely here: | ||||
| 	if o.strategy=='CUTOUT': | ||||
| 		#ob=bpy.context.active_object | ||||
| 		offset=True | ||||
| 		if o.cut_type=='ONLINE' and o.onlycurves==True:#is separate to allow open curves :) | ||||
| 			print('separe') | ||||
| 			chunksFromCurve=[] | ||||
| 			for ob in o.objects: | ||||
| 				chunksFromCurve.extend(curveToChunks(ob)) | ||||
| 			p=Polygon.Polygon()	 | ||||
| 			for ch in chunksFromCurve: | ||||
| 				#print(ch.points) | ||||
| 				 | ||||
| 				if len(ch.points)>2: | ||||
| 					ch.poly=chunkToShapely(ch) | ||||
| 					#p.addContour(ch.poly) | ||||
| 		else: | ||||
| 			chunksFromCurve=[] | ||||
| 			if o.cut_type=='ONLINE': | ||||
| 				p=getObjectOutline(0,o,True) | ||||
| 				 | ||||
| 			else: | ||||
| 				offset=True | ||||
| 				if o.cut_type=='INSIDE': | ||||
| 					offset=False | ||||
| 					 | ||||
| 				p=getObjectOutline(o.cutter_diameter/2,o,offset) | ||||
| 				if o.outlines_count>1: | ||||
| 					for i in range(1,o.outlines_count): | ||||
| 						chunksFromCurve.extend(shapelyToChunks(p,-1)) | ||||
| 						p = p.buffer(distance = o.dist_between_paths * offset, resolution = o.circle_detail) | ||||
| 						 | ||||
| 					 | ||||
| 			chunksFromCurve.extend(shapelyToChunks(p,-1)) | ||||
| 			if o.outlines_count>1 and o.movement_insideout=='OUTSIDEIN': | ||||
| 				chunksFromCurve.reverse() | ||||
| 		#parentChildPoly(chunksFromCurve,chunksFromCurve,o) | ||||
| 		chunksFromCurve=limitChunks(chunksFromCurve,o) | ||||
| 		parentChildPoly(chunksFromCurve,chunksFromCurve,o) | ||||
| 		if o.outlines_count==1: | ||||
| 			chunksFromCurve=sortChunks(chunksFromCurve,o) | ||||
| 		strategy_cutout( o ) | ||||
| 		 | ||||
| 		#if o.outlines_count>0 and o.cut_type!='ONLINE' and o.movement_insideout=='OUTSIDEIN':#reversing just with more outlines | ||||
| 		#	chunksFromCurve.reverse() | ||||
| 						 | ||||
| 		if (o.movement_type=='CLIMB' and o.spindle_rotation_direction=='CCW') or (o.movement_type=='CONVENTIONAL' and o.spindle_rotation_direction=='CW'): | ||||
| 			for ch in chunksFromCurve: | ||||
| 				ch.points.reverse() | ||||
| 			 | ||||
| 		if o.cut_type=='INSIDE':#there would bee too many conditions above, so for now it gets reversed once again when inside cutting. | ||||
| 			for ch in chunksFromCurve: | ||||
| 				ch.points.reverse() | ||||
| 				 | ||||
| 		 | ||||
| 		if o.use_layers: | ||||
| 			layers=[] | ||||
| 			n=math.ceil((o.maxz-o.min.z)/o.stepdown) | ||||
| 			layerstart=o.maxz | ||||
| 			for x in range(0,n): | ||||
| 				layerend=max(o.maxz-((x+1)*o.stepdown),o.min.z) | ||||
| 				if int(layerstart*10**8)!=int(layerend*10**8):#it was possible that with precise same end of operation, last layer was done 2x on exactly same level... | ||||
| 					layers.append([layerstart,layerend]) | ||||
| 				layerstart=layerend | ||||
| 		else: | ||||
| 				layers=[[o.maxz,o.min.z]] | ||||
| 			 | ||||
| 		print(layers) | ||||
| 		extendorder=[] | ||||
| 		if o.first_down:#each shape gets either cut all the way to bottom, or every shape gets cut 1 layer, then all again. has to create copies, because same chunks are worked with on more layers usually | ||||
| 			for chunk in chunksFromCurve: | ||||
| 				for layer in layers: | ||||
| 					extendorder.append([chunk.copy(),layer]) | ||||
| 		else: | ||||
| 			for layer in layers: | ||||
| 				for chunk in chunksFromCurve: | ||||
| 					extendorder.append([chunk.copy(),layer]) | ||||
| 		 | ||||
| 		for chl in extendorder:#Set Z for all chunks | ||||
| 			chunk=chl[0] | ||||
| 			layer=chl[1] | ||||
| 			print(layer[1]) | ||||
| 			chunk.setZ(layer[1]) | ||||
| 		 | ||||
| 		chunks=[] | ||||
| 		 | ||||
| 		if o.ramp:#add ramps or simply add chunks | ||||
| 			for chl in extendorder: | ||||
| 				chunk=chl[0] | ||||
| 				layer=chl[1] | ||||
| 				if chunk.closed: | ||||
| 					chunk.rampContour(layer[0],layer[1],o) | ||||
| 				else: | ||||
| 					chunk.rampZigZag(layer[0],layer[1],o) | ||||
| 			 | ||||
| 		 | ||||
| 		 | ||||
| 		if o.use_bridges:#add bridges to chunks | ||||
| 			#bridges=getBridges(p,o) | ||||
| 			bridgeheight=min(0,o.min.z+o.bridges_height) | ||||
| 			for chl in extendorder: | ||||
| 				chunk=chl[0] | ||||
| 				layer=chl[1] | ||||
| 				if layer[1]<bridgeheight: | ||||
| 					addBridges(chunk,o) | ||||
| 		 | ||||
| 		 | ||||
| 		 | ||||
| 		for chl in extendorder: | ||||
| 			chunks.append(chl[0]) | ||||
| 		 | ||||
| 						 | ||||
| 		 | ||||
| 
 | ||||
| 		chunksToMesh(chunks,o) | ||||
| 			 | ||||
| 	elif o.strategy=='CURVE': | ||||
| 		pathSamples=[] | ||||
| 		getOperationSources(o) | ||||
| 		if not o.onlycurves: | ||||
| 			o.warnings+= 'at least one of assigned objects is not a curve' | ||||
| 		#ob=bpy.data.objects[o.object_name] | ||||
| 		for ob in o.objects: | ||||
| 			pathSamples.extend(curveToChunks(ob)) | ||||
| 		pathSamples=sortChunks(pathSamples,o)#sort before sampling | ||||
| 		pathSamples=chunksRefine(pathSamples,o) | ||||
| 		 | ||||
| 		if o.ramp: | ||||
| 			for ch in pathSamples: | ||||
| 				nchunk = ch.rampZigZag(ch.zstart, ch.points[0][2],o) | ||||
| 				ch.points=nchunk.points | ||||
| 		strategy_curve( o ) | ||||
| 				 | ||||
| 		chunksToMesh(pathSamples,o) | ||||
| 	elif o.strategy=='PROJECTED_CURVE': | ||||
| 		strategy_proj_curve(s, o) | ||||
| 		 | ||||
| 		 | ||||
| 		 | ||||
| 	if o.strategy=='PROJECTED_CURVE': | ||||
| 		pathSamples=[] | ||||
| 		chunks=[] | ||||
| 		ob=bpy.data.objects[o.curve_object] | ||||
| 		pathSamples.extend(curveToChunks(ob)) | ||||
| 		 | ||||
| 		targetCurve=s.objects[o.curve_object1] | ||||
| 		 | ||||
| 		from cam import chunk | ||||
| 		if targetCurve.type!='CURVE': | ||||
| 			o.warnings=o.warnings+'Projection target and source have to be curve objects!\n ' | ||||
| 			return | ||||
| 		'''	#mesh method is highly unstable, I don't like itwould be there at all.... better to use curves. | ||||
| 		if targetCurve.type=='MESH': | ||||
| 			 | ||||
| 			c=targetCurve | ||||
| 			for ch in pathSamples: | ||||
| 				ch.depth=0 | ||||
| 				for i,s in enumerate(ch.points): | ||||
| 					np=c.closest_point_on_mesh(s) | ||||
| 					ch.startpoints.append(Vector(s)) | ||||
| 					ch.endpoints.append(np[0]) | ||||
| 					ch.rotations.append((0,0,0)) | ||||
| 					vect = np[0]-Vector(s) | ||||
| 					 | ||||
| 					ch.depth=min(ch.depth,-vect.length) | ||||
| 		else: | ||||
| 		''' | ||||
| 		if 1: | ||||
| 			extend_up=0.1 | ||||
| 			extend_down=0.04 | ||||
| 			tsamples = curveToChunks(targetCurve) | ||||
| 			for chi,ch in enumerate(pathSamples): | ||||
| 				cht=tsamples[chi].points | ||||
| 				ch.depth=0 | ||||
| 				for i,s in enumerate(ch.points): | ||||
| 					#move the points a bit | ||||
| 					ep=Vector(cht[i]) | ||||
| 					sp=Vector(ch.points[i]) | ||||
| 					#extend startpoint | ||||
| 					vecs=sp-ep | ||||
| 					vecs.normalize() | ||||
| 					vecs*=extend_up | ||||
| 					sp+=vecs | ||||
| 					ch.startpoints.append(sp) | ||||
| 					 | ||||
| 					#extend endpoint | ||||
| 					vece=sp-ep | ||||
| 					vece.normalize() | ||||
| 					vece*=extend_down | ||||
| 					ep-=vece | ||||
| 					ch.endpoints.append(ep) | ||||
| 					 | ||||
| 					 | ||||
| 					ch.rotations.append((0,0,0)) | ||||
| 					 | ||||
| 					vec=sp-ep | ||||
| 					ch.depth=min(ch.depth,-vec.length) | ||||
| 					ch.points[i]=sp.copy() | ||||
| 				 | ||||
| 				 | ||||
| 			 | ||||
| 		if o.use_layers: | ||||
| 			n=math.ceil(-(ch.depth/o.stepdown)) | ||||
| 			layers=[] | ||||
| 			for x in range(0,n): | ||||
| 				 | ||||
| 				layerstart=-(x*o.stepdown) | ||||
| 				layerend=max(-((x+1)*o.stepdown),ch.depth) | ||||
| 				layers.append([layerstart,layerend]) | ||||
| 		else: | ||||
| 			layerstart=0# | ||||
| 			layerend=ch.depth# | ||||
| 			layers=[[layerstart,layerend]] | ||||
| 		 | ||||
| 		chunks.extend(sampleChunksNAxis(o,pathSamples,layers)) | ||||
| 		#for ch in pathSamples: | ||||
| 		#	ch.points=ch.endpoints | ||||
| 		chunksToMesh(chunks,o) | ||||
| 		 | ||||
| 		 | ||||
| 	if o.strategy=='POCKET':	 | ||||
| 	elif o.strategy=='POCKET':	 | ||||
| 		p=getObjectOutline(o.cutter_diameter/2,o,False) | ||||
| 		#all=Polygon.Polygon(p) | ||||
| 		approxn=(min(o.max.x-o.min.x,o.max.y-o.min.y)/o.dist_between_paths)/2 | ||||
|  | @ -3033,6 +3052,7 @@ def getPath3axis(context,operation): | |||
| 		chunks=sortChunks(chunks,o) | ||||
| 		print(chunks) | ||||
| 		chunksToMesh(chunks,o) | ||||
| 		 | ||||
| 	elif o.strategy=='MEDIAL_AXIS': | ||||
| 		print('doing highly experimental stuff') | ||||
| 		 | ||||
|  | @ -3473,5 +3493,3 @@ def reload_paths(o): | |||
| 	 | ||||
| 	if old_pathmesh != None: | ||||
| 		bpy.data.meshes.remove(old_pathmesh) | ||||
| 
 | ||||
| 	 | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 vilemnovak
						vilemnovak