kopia lustrzana https://github.com/vilemduha/blendercam
Merge pull request #136 from joemarshall/numpy_chunk
Make chunk use numpy (and optimise with numba)pull/258/head
commit
b3c1eeda06
|
@ -25,7 +25,7 @@ jobs:
|
|||
- name: Cache blender
|
||||
id: cache-blender
|
||||
if: runner.os != 'macOS'
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: blender
|
||||
key: ${{ matrix.os }}-${{ matrix.blender_version}}-blender
|
||||
|
@ -57,7 +57,7 @@ jobs:
|
|||
shutil.unpack_archive("${{ steps.download.outputs.BLENDER_ARCHIVE }}","blender")
|
||||
shell: python
|
||||
- name: Save blender
|
||||
uses: actions/cache/save@v3
|
||||
uses: actions/cache/save@v4
|
||||
if: steps.cache-blender.outputs.cache-hit != 'true' && runner.os != 'macOS'
|
||||
with:
|
||||
path: blender
|
||||
|
@ -79,21 +79,10 @@ jobs:
|
|||
export ADDON_PATH=${PWD}/scripts/addons/blendercam.zip
|
||||
cd scripts/addons/cam/tests
|
||||
python install_addon.py ${ADDON_PATH}
|
||||
python test_suite.py
|
||||
python test_suite.py -vvv
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: blendercam-${{matrix.os}}-${{matrix.blender_version}}
|
||||
path: ./scripts/addons/cam
|
||||
rerun-failed-jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ build_and_test ]
|
||||
if: failure()
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Rerun failed jobs in the current workflow (because mac blender is unstable)
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh run rerun ${{ github.run_id }} --failed
|
||||
|
||||
|
|
|
@ -23,3 +23,5 @@ forceSyncWithUpstream
|
|||
.project
|
||||
|
||||
.pydevproject
|
||||
__pycache__/
|
||||
temp_cam/
|
|
@ -17,9 +17,7 @@
|
|||
# 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 bgl
|
||||
# ***** END GPL LICENCE BLOCK ****
|
||||
import bl_operators
|
||||
import blf
|
||||
import bpy
|
||||
|
@ -43,6 +41,8 @@ except ImportError:
|
|||
subprocess.check_call([sys.executable, "-m", "ensurepip"])
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", " pip"])
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "shapely","Equation","opencamlib"])
|
||||
# install numba if available for this platform, ignore failure
|
||||
subprocess.run([sys.executable, "-m", "pip", "install", "numba"])
|
||||
|
||||
|
||||
from bpy.app.handlers import persistent
|
||||
|
|
|
@ -21,6 +21,9 @@ class AsyncOperatorMixin:
|
|||
self._is_cancelled=False
|
||||
|
||||
def modal(self,context,event):
|
||||
if bpy.app.background:
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
if event.type == 'TIMER':
|
||||
try:
|
||||
if self.tick(context):
|
||||
|
@ -70,6 +73,8 @@ class AsyncOperatorMixin:
|
|||
return True
|
||||
except StopIteration:
|
||||
return False
|
||||
except Exception as e:
|
||||
print("Exception thrown in tick:",e)
|
||||
|
||||
def execute(self, context):
|
||||
if bpy.app.background:
|
||||
|
|
|
@ -18,6 +18,8 @@ class UpdateChecker(bpy.types.Operator):
|
|||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
if bpy.app.background:
|
||||
return {"FINISHED"}
|
||||
last_update_check = bpy.context.preferences.addons['cam'].preferences.last_update_check
|
||||
today=date.today().toordinal()
|
||||
update_source = bpy.context.preferences.addons['cam'].preferences.update_source
|
||||
|
|
|
@ -138,20 +138,21 @@ def useBridges(ch, o):
|
|||
|
||||
vi = 0
|
||||
newpoints = []
|
||||
p1 = sgeometry.Point(ch.points[0])
|
||||
ch_points=ch.get_points_np()
|
||||
p1 = sgeometry.Point(ch_points[0])
|
||||
startinside = o.bridgespoly.contains(p1)
|
||||
interrupted = False
|
||||
verts = []
|
||||
edges = []
|
||||
faces = []
|
||||
while vi < len(ch.points):
|
||||
while vi < len(ch_points):
|
||||
i1 = vi
|
||||
i2 = vi
|
||||
chp1 = ch.points[i1]
|
||||
chp2 = ch.points[i1] # Vector(v1)#this is for case of last point and not closed chunk..
|
||||
if vi + 1 < len(ch.points):
|
||||
chp1 = ch_points[i1]
|
||||
chp2 = ch_points[i1] # Vector(v1)#this is for case of last point and not closed chunk..
|
||||
if vi + 1 < len(ch_points):
|
||||
i2 = vi + 1
|
||||
chp2 = ch.points[vi + 1] # Vector(ch.points[vi+1])
|
||||
chp2 = ch_points[vi + 1] # Vector(ch_points[vi+1])
|
||||
v1 = mathutils.Vector(chp1)
|
||||
v2 = mathutils.Vector(chp2)
|
||||
if v1.z < bridgeheight or v2.z < bridgeheight:
|
||||
|
@ -230,7 +231,7 @@ def useBridges(ch, o):
|
|||
newpoints.append(chp1)
|
||||
vi += 1
|
||||
interrupted = True
|
||||
ch.points = newpoints
|
||||
ch.set_points(newpoints)
|
||||
|
||||
# create bridge cut curve here
|
||||
count = 0
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -59,6 +59,7 @@ from cam.image_utils import *
|
|||
from cam.opencamlib.opencamlib import *
|
||||
from cam.nc import iso
|
||||
|
||||
PROFILING=False # set this true to run cprofile on code
|
||||
|
||||
def pointonline(a, b, c, tolerence):
|
||||
b = b - a # convert to vector by subtracting origin
|
||||
|
@ -158,6 +159,7 @@ def exportGcodePath(filename, vertslist, operations):
|
|||
if split:
|
||||
fileindex = '_' + str(findex)
|
||||
filename = basefilename + fileindex + extension
|
||||
print("writing: ",filename)
|
||||
c = postprocessor.Creator()
|
||||
|
||||
# process user overrides for post processor settings
|
||||
|
@ -517,8 +519,6 @@ def exportGcodePath(filename, vertslist, operations):
|
|||
async def getPath(context, operation): # should do all path calculations.
|
||||
t = time.process_time()
|
||||
# print('ahoj0')
|
||||
if shapely.speedups.available:
|
||||
shapely.speedups.enable()
|
||||
|
||||
# these tags are for caching of some of the results. Not working well still
|
||||
# - although it can save a lot of time during calculation...
|
||||
|
@ -543,7 +543,19 @@ async def getPath(context, operation): # should do all path calculations.
|
|||
print(operation.machine_axes)
|
||||
|
||||
if operation.machine_axes == '3':
|
||||
await getPath3axis(context, operation)
|
||||
if PROFILING==True: # profiler
|
||||
import cProfile, pstats, io
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
await getPath3axis(context, operation)
|
||||
pr.disable()
|
||||
s = io.StringIO()
|
||||
sortby = pstats.SortKey.CALLS
|
||||
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
|
||||
ps.print_stats()
|
||||
print(s.getvalue())
|
||||
else:
|
||||
await getPath3axis(context, operation)
|
||||
|
||||
elif (operation.machine_axes == '5' and operation.strategy5axis == 'INDEXED') or (
|
||||
operation.machine_axes == '4' and operation.strategy4axis == 'INDEXED'):
|
||||
|
@ -680,12 +692,13 @@ async def getPath3axis(context, operation):
|
|||
chunks = await utils.connectChunksLow(chunks, o)
|
||||
if o.movement.ramp:
|
||||
for ch in chunks:
|
||||
ch.rampZigZag(ch.zstart, ch.points[0][2], o)
|
||||
ch.rampZigZag(ch.zstart, None, o)
|
||||
# print(chunks)
|
||||
if o.strategy == 'CARVE':
|
||||
for ch in chunks:
|
||||
for vi in range(0, len(ch.points)):
|
||||
ch.points[vi] = (ch.points[vi][0], ch.points[vi][1], ch.points[vi][2] - o.carve_depth)
|
||||
ch.offsetZ(-o.carve_depth)
|
||||
# for vi in range(0, len(ch.points)):
|
||||
# ch.points[vi] = (ch.points[vi][0], ch.points[vi][1], ch.points[vi][2] - o.carve_depth)
|
||||
if o.use_bridges:
|
||||
print(chunks)
|
||||
for bridge_chunk in chunks:
|
||||
|
@ -701,7 +714,8 @@ async def getPath3axis(context, operation):
|
|||
if (o.movement.type == 'CLIMB' and o.movement.spindle_rotation == 'CW') or (
|
||||
o.movement.type == 'CONVENTIONAL' and o.movement.spindle_rotation == 'CCW'):
|
||||
for ch in chunks:
|
||||
ch.points.reverse()
|
||||
ch.reverse()
|
||||
|
||||
strategy.chunksToMesh(chunks, o)
|
||||
|
||||
elif o.strategy == 'WATERLINE' and not o.optimisation.use_opencamlib:
|
||||
|
@ -826,7 +840,7 @@ async def getPath3axis(context, operation):
|
|||
if (o.movement.type == 'CONVENTIONAL' and o.movement.spindle_rotation == 'CCW') or (
|
||||
o.movement.type == 'CLIMB' and o.movement.spindle_rotation == 'CW'):
|
||||
for chunk in slicechunks:
|
||||
chunk.points.reverse()
|
||||
chunk.reverse()
|
||||
slicechunks = await utils.sortChunks(slicechunks, o)
|
||||
if topdown:
|
||||
slicechunks.reverse()
|
||||
|
@ -835,7 +849,6 @@ async def getPath3axis(context, operation):
|
|||
chunks.extend(slicechunks)
|
||||
if topdown:
|
||||
chunks.reverse()
|
||||
|
||||
strategy.chunksToMesh(chunks, o)
|
||||
|
||||
elif o.strategy == 'DRILL':
|
||||
|
|
|
@ -35,6 +35,9 @@ from cam.chunk import *
|
|||
from cam import simulation
|
||||
from cam.async_op import progress_async
|
||||
|
||||
from cam.numba_wrapper import jit,prange
|
||||
|
||||
|
||||
def getCircle(r, z):
|
||||
car = numpy.full(shape=(r*2,r*2),fill_value=-10,dtype=numpy.double)
|
||||
res = 2 * r
|
||||
|
@ -128,6 +131,12 @@ def imagetonumpy(i):
|
|||
return na
|
||||
|
||||
|
||||
@jit(nopython=True,parallel=True,fastmath=False,cache=True)
|
||||
def _offset_inner_loop(y1,y2,cutterArrayNan,cwidth,sourceArray,width,height,comparearea):
|
||||
for y in prange(y1,y2):
|
||||
for x in range(0,width-cwidth):
|
||||
comparearea[x,y] = numpy.nanmax(sourceArray[x:x+cwidth,y:y+cwidth] + cutterArrayNan)
|
||||
|
||||
async def offsetArea(o, samples):
|
||||
""" offsets the whole image with the cutter + skin offsets """
|
||||
if o.update_offsetimage_tag:
|
||||
|
@ -141,7 +150,7 @@ async def offsetArea(o, samples):
|
|||
width = len(sourceArray)
|
||||
height = len(sourceArray[0])
|
||||
cwidth = len(cutterArray)
|
||||
o.offset_image= numpy.full(shape=(width,height),fill_value=-10,dtype=numpy.float)
|
||||
o.offset_image= numpy.full(shape=(width,height),fill_value=-10.0,dtype=numpy.double)
|
||||
|
||||
t = time.time()
|
||||
|
||||
|
@ -149,18 +158,14 @@ async def offsetArea(o, samples):
|
|||
|
||||
if o.inverse:
|
||||
sourceArray = -sourceArray + minz
|
||||
print(o.offset_image.shape)
|
||||
comparearea = o.offset_image[m: width - cwidth + m, m:height - cwidth + m]
|
||||
# i=0
|
||||
for x in range(0, cwidth): # cwidth):
|
||||
text = "Offsetting depth " + str(int(x * 100 / cwidth))
|
||||
# o.operator.report({"INFO"}, text)
|
||||
await progress_async('offset depth image', int(x * 100 / cwidth))
|
||||
for y in range(0, cwidth):
|
||||
if cutterArray[x, y] > -10:
|
||||
numpy.maximum(sourceArray[x: width - cwidth + x, y: height - cwidth + y] + cutterArray[x, y],
|
||||
comparearea, comparearea)
|
||||
|
||||
cutterArrayNan=np.where(cutterArray>-10,cutterArray,np.full(cutterArray.shape,np.nan))
|
||||
for y in range(0,10):
|
||||
y1 = (y * comparearea.shape[1])//10
|
||||
y2 = ((y+1) * comparearea.shape[1])//10
|
||||
_offset_inner_loop(y1,y2,cutterArrayNan,cwidth,sourceArray,width,height,comparearea)
|
||||
await progress_async('offset depth image', int((y2 * 100) / comparearea.shape[1]))
|
||||
o.offset_image[m: width - cwidth + m, m:height - cwidth + m] = comparearea
|
||||
|
||||
print('\nOffset image time ' + str(time.time() - t))
|
||||
|
@ -196,10 +201,11 @@ def getOffsetImageCavities(o, i): # for pencil operation mainly
|
|||
# ##crop pixels that are on outer borders
|
||||
for chi in range(len(chunks) - 1, -1, -1):
|
||||
chunk = chunks[chi]
|
||||
for si in range(len(chunk.points) - 1, -1, -1):
|
||||
if not (o.min.x < chunk.points[si][0] < o.max.x and o.min.y < chunk.points[si][1] < o.max.y):
|
||||
chunk.points.pop(si)
|
||||
if len(chunk.points) < 2:
|
||||
chunk.clip_points(o.min.x,o.max.x,o.min.y,o.max.y)
|
||||
# for si in range(len(chunk.points) - 1, -1, -1):
|
||||
# if not (o.min.x < chunk.points[si][0] < o.max.x and o.min.y < chunk.points[si][1] < o.max.y):
|
||||
# chunk.points.pop(si)
|
||||
if chunk.count() < 2:
|
||||
chunks.pop(chi)
|
||||
|
||||
return chunks
|
||||
|
@ -217,10 +223,10 @@ def imageEdgeSearch_online(o, ar, zimage): # search edges for pencil strategy,
|
|||
indices = ar.nonzero() # first get white pixels
|
||||
startpix = ar.sum()
|
||||
totpix = startpix
|
||||
chunks = []
|
||||
chunk_builders = []
|
||||
xs = indices[0][0]
|
||||
ys = indices[1][0]
|
||||
nchunk = camPathChunk([(xs, ys, zimage[xs, ys])]) # startposition
|
||||
nchunk = camPathChunkBuilder([(xs, ys, zimage[xs, ys])]) # startposition
|
||||
dindex = 0 # index in the directions list
|
||||
last_direction = directions[dindex]
|
||||
test_direction = directions[dindex]
|
||||
|
@ -276,15 +282,15 @@ def imageEdgeSearch_online(o, ar, zimage): # search edges for pencil strategy,
|
|||
testangulardistance = 0
|
||||
indices = ar.nonzero()
|
||||
totpix = len(indices[0])
|
||||
chunks.append(nchunk)
|
||||
chunk_builders.append(nchunk)
|
||||
if len(indices[0] > 0):
|
||||
xs = indices[0][0]
|
||||
ys = indices[1][0]
|
||||
nchunk = camPathChunk([(xs, ys, zimage[xs, ys])]) # startposition
|
||||
nchunk = camPathChunkBuilder([(xs, ys, zimage[xs, ys])]) # startposition
|
||||
|
||||
ar[xs, ys] = False
|
||||
else:
|
||||
nchunk = camPathChunk([])
|
||||
nchunk = camPathChunkBuilder([])
|
||||
|
||||
test_direction = directions[3]
|
||||
last_direction = directions[3]
|
||||
|
@ -321,19 +327,19 @@ def imageEdgeSearch_online(o, ar, zimage): # search edges for pencil strategy,
|
|||
# print(totpix)
|
||||
# print(totaltests)
|
||||
i = 0
|
||||
chunks.append(nchunk)
|
||||
for ch in chunks:
|
||||
chunk_builders.append(nchunk)
|
||||
for ch in chunk_builders:
|
||||
ch = ch.points
|
||||
for i in range(0, len(ch)):
|
||||
ch[i] = ((ch[i][0] + coef - o.borderwidth) * o.optimisation.pixsize + minx,
|
||||
(ch[i][1] + coef - o.borderwidth) * o.optimisation.pixsize + miny, ch[i][2])
|
||||
return chunks
|
||||
return [c.to_chunk() for c in chunk_builders]
|
||||
|
||||
|
||||
def crazyPath(o):
|
||||
async def crazyPath(o):
|
||||
# TODO: try to do something with this stuff, it's just a stub. It should be a greedy adaptive algorithm.
|
||||
# started another thing below.
|
||||
prepareArea(o)
|
||||
await prepareArea(o)
|
||||
sx = o.max.x - o.min.x
|
||||
sy = o.max.y - o.min.y
|
||||
|
||||
|
@ -394,14 +400,14 @@ def crazyStrokeImage(o):
|
|||
indices = ar.nonzero() # first get white pixels
|
||||
startpix = ar.sum() #
|
||||
totpix = startpix
|
||||
chunks = []
|
||||
chunk_builders = []
|
||||
xs = indices[0][0] - r
|
||||
if xs < r:
|
||||
xs = r
|
||||
ys = indices[1][0] - r
|
||||
if ys < r:
|
||||
ys = r
|
||||
nchunk = camPathChunk([(xs, ys)]) # startposition
|
||||
nchunk = camPathChunkBuilder([(xs, ys)]) # startposition
|
||||
print(indices)
|
||||
print(indices[0][0], indices[1][0])
|
||||
lastvect = Vector((r, 0, 0)) # vector is 3d, blender somehow doesn't rotate 2d vectors with angles.
|
||||
|
@ -514,7 +520,7 @@ def crazyStrokeImage(o):
|
|||
if itests > maxtests or testlength > r * 1.5:
|
||||
# print('resetting location')
|
||||
indices = ar.nonzero()
|
||||
chunks.append(nchunk)
|
||||
chunk_builders.append(nchunk)
|
||||
if len(indices[0]) > 0:
|
||||
xs = indices[0][0] - r
|
||||
if xs < r:
|
||||
|
@ -522,7 +528,7 @@ def crazyStrokeImage(o):
|
|||
ys = indices[1][0] - r
|
||||
if ys < r:
|
||||
ys = r
|
||||
nchunk = camPathChunk([(xs, ys)]) # startposition
|
||||
nchunk = camPathChunkBuilder([(xs, ys)]) # startposition
|
||||
ar[xs - r:xs - r + d, ys - r:ys - r + d] = ar[xs - r:xs - r + d,
|
||||
ys - r:ys - r + d] * cutterArrayNegative
|
||||
r = random.random() * 2 * pi
|
||||
|
@ -539,13 +545,13 @@ def crazyStrokeImage(o):
|
|||
print(totpix)
|
||||
print(totaltests)
|
||||
i = 0
|
||||
chunks.append(nchunk)
|
||||
for ch in chunks:
|
||||
chunk_builders.append(nchunk)
|
||||
for ch in chunk_builders:
|
||||
ch = ch.points
|
||||
for i in range(0, len(ch)):
|
||||
ch[i] = ((ch[i][0] + coef - o.borderwidth) * o.optimisation.pixsize + minx,
|
||||
(ch[i][1] + coef - o.borderwidth) * o.optimisation.pixsize + miny, 0)
|
||||
return chunks
|
||||
return [c.to_chunk() for c in chunk_builders]
|
||||
|
||||
|
||||
def crazyStrokeImageBinary(o, ar, avoidar):
|
||||
|
@ -582,7 +588,7 @@ def crazyStrokeImageBinary(o, ar, avoidar):
|
|||
startpix = ar.sum() #
|
||||
totpix = startpix
|
||||
|
||||
chunks = []
|
||||
chunk_builders = []
|
||||
# try to find starting point here
|
||||
|
||||
xs = indices[0][0] - r / 2
|
||||
|
@ -592,7 +598,7 @@ def crazyStrokeImageBinary(o, ar, avoidar):
|
|||
if ys < r:
|
||||
ys = r
|
||||
|
||||
nchunk = camPathChunk([(xs, ys)]) # startposition
|
||||
nchunk = camPathChunkBuilder([(xs, ys)]) # startposition
|
||||
print(indices)
|
||||
print(indices[0][0], indices[1][0])
|
||||
lastvect = Vector((r, 0, 0)) # vector is 3d, blender somehow doesn't rotate 2d vectors with angles.
|
||||
|
@ -741,7 +747,7 @@ def crazyStrokeImageBinary(o, ar, avoidar):
|
|||
indices = andar.nonzero()
|
||||
if len(nchunk.points) > 1:
|
||||
chunk.parentChildDist([nchunk], chunks, o, distance=r)
|
||||
chunks.append(nchunk)
|
||||
chunk_builders.append(nchunk)
|
||||
|
||||
if totpix > startpix * 0.001:
|
||||
found = False
|
||||
|
@ -797,15 +803,15 @@ def crazyStrokeImageBinary(o, ar, avoidar):
|
|||
i = 0
|
||||
if len(nchunk.points) > 1:
|
||||
chunk.parentChildDist([nchunk], chunks, o, distance=r)
|
||||
chunks.append(nchunk)
|
||||
chunk_builders.append(nchunk)
|
||||
|
||||
for ch in chunks:
|
||||
for ch in chunk_builders:
|
||||
ch = ch.points
|
||||
for i in range(0, len(ch)):
|
||||
ch[i] = ((ch[i][0] + coef - o.borderwidth) * o.optimisation.pixsize + minx,
|
||||
(ch[i][1] + coef - o.borderwidth) * o.optimisation.pixsize + miny, o.minz)
|
||||
|
||||
return chunks
|
||||
return [c.to_chunk for c in chunk_builders]
|
||||
|
||||
|
||||
def imageToChunks(o, image, with_border=False):
|
||||
|
@ -967,12 +973,12 @@ def imageToChunks(o, image, with_border=False):
|
|||
|
||||
s = curve_simplify.simplify_RDP(ch, soptions)
|
||||
# print(s)
|
||||
nch = camPathChunk([])
|
||||
nch = camPathChunkBuilder([])
|
||||
for i in range(0, len(s)):
|
||||
nch.points.append((ch[s[i]].x, ch[s[i]].y))
|
||||
|
||||
if len(nch.points) > 2:
|
||||
nchunks.append(nch)
|
||||
nchunks.append(nch.to_chunk())
|
||||
|
||||
return nchunks
|
||||
else:
|
||||
|
@ -985,7 +991,6 @@ def imageToShapely(o, i, with_border=False):
|
|||
|
||||
return polys
|
||||
|
||||
|
||||
def getSampleImage(s, sarray, minz):
|
||||
x = s[0]
|
||||
y = s[1]
|
||||
|
@ -996,10 +1001,14 @@ def getSampleImage(s, sarray, minz):
|
|||
maxx = minx + 1
|
||||
miny = floor(y)
|
||||
maxy = miny + 1
|
||||
s1a = sarray.item(minx, miny) # most optimal access to array so far
|
||||
s2a = sarray.item(maxx, miny)
|
||||
s1b = sarray.item(minx, maxy)
|
||||
s2b = sarray.item(maxx, maxy)
|
||||
s1a=sarray[minx,miny]
|
||||
s2a=sarray[maxx,miny]
|
||||
s1b=sarray[minx,maxy]
|
||||
s2b=sarray[maxx,maxy]
|
||||
# s1a = sarray.item(minx, miny) # most optimal access to array so far
|
||||
# s2a = sarray.item(maxx, miny)
|
||||
# s1b = sarray.item(minx, maxy)
|
||||
# s2b = sarray.item(maxx, maxy)
|
||||
|
||||
sa = s1a * (maxx - x) + s2a * (x - minx)
|
||||
sb = s1b * (maxx - x) + s2b * (x - minx)
|
||||
|
@ -1057,7 +1066,18 @@ def renderSampleImage(o):
|
|||
r = s.render
|
||||
r.resolution_x = resx
|
||||
r.resolution_y = resy
|
||||
r.engine = 'BLENDER_EEVEE'
|
||||
if bpy.app.background:
|
||||
# in CI we use cycles because it
|
||||
# works without opengl support
|
||||
r.engine = 'CYCLES'
|
||||
cycles_settings=s.cycles.items()
|
||||
s.cycles.samples = 1
|
||||
bpy.context.view_layer.samples=1
|
||||
vl_settings=bpy.context.view_layer.cycles
|
||||
vl_settings.use_denoising=False
|
||||
else:
|
||||
r.engine = 'BLENDER_EEVEE'
|
||||
|
||||
|
||||
n.links.clear()
|
||||
n.nodes.clear()
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
try:
|
||||
from numba import jit,prange
|
||||
print("numba: yes")
|
||||
except:
|
||||
print("numba: no")
|
||||
def jit(f=None, *args, **kwargs):
|
||||
def decorator(func):
|
||||
return func
|
||||
|
||||
if callable(f):
|
||||
return f
|
||||
else:
|
||||
return decorator
|
||||
prange = range
|
|
@ -82,7 +82,7 @@ async def ocl_sample(operation, chunks,use_cached_mesh = False):
|
|||
bdc.setCutter(cutter)
|
||||
|
||||
for chunk in chunks:
|
||||
for coord in chunk.points:
|
||||
for coord in chunk.get_points_np():
|
||||
bdc.appendPoint(ocl.CLPoint(coord[0] * 1000, coord[1] * 1000, op_minz * 1000))
|
||||
await progress_async("OpenCAMLib sampling")
|
||||
bdc.run()
|
||||
|
|
|
@ -10,6 +10,8 @@ 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
|
||||
|
@ -18,6 +20,7 @@ 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
|
||||
|
||||
|
@ -32,30 +35,43 @@ def pointSamplesFromOCL(points, samples):
|
|||
def chunkPointSamplesFromOCL(chunks, samples):
|
||||
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
|
||||
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:
|
||||
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
|
||||
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):
|
||||
|
@ -100,11 +116,14 @@ async def oclResampleChunks(operation, chunks_to_resample,use_cached_mesh):
|
|||
|
||||
sample_index = 0
|
||||
for chunk, i_start, i_length in chunks_to_resample:
|
||||
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
|
||||
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):
|
||||
|
@ -155,18 +174,25 @@ async def oclGetWaterline(operation, chunks):
|
|||
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:
|
||||
chunks.append(camPathChunk(inpoints=[]))
|
||||
inpoints=[]
|
||||
for p in l:
|
||||
chunks[-1].points.append((p.x / OCL_SCALE, p.y / OCL_SCALE, p.z / OCL_SCALE))
|
||||
chunks[-1].append(chunks[-1].points[0])
|
||||
chunks[-1].closed = True
|
||||
chunks[-1].poly = sgeometry.Polygon(chunks[-1].points)
|
||||
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):
|
||||
|
|
|
@ -190,9 +190,8 @@ async def _calc_path(operator,context):
|
|||
if o.use_layers:
|
||||
o.movement.parallel_step_back = False
|
||||
try:
|
||||
print("Get path:",context)
|
||||
await gcodepath.getPath(context, o)
|
||||
print("Got path:",context)
|
||||
print("Got path okay")
|
||||
except CamException as e:
|
||||
traceback.print_tb(e.__traceback__)
|
||||
error_str="\n".join(textwrap.wrap(str(e),width=80))
|
||||
|
@ -229,6 +228,7 @@ class CalculatePath(bpy.types.Operator,AsyncOperatorMixin):
|
|||
|
||||
async def execute_async(self, context):
|
||||
(retval,success) = await _calc_path(self,context)
|
||||
print(f"CALCULATED PATH (success={success},retval={retval}")
|
||||
return retval
|
||||
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ def getPathPatternParallel(o, angle):
|
|||
dirvect *= pathstep
|
||||
for a in range(int(-dim / pathd),
|
||||
int(dim / pathd)): # this is highly ineffective, computes path2x the area needed...
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
v = Vector((a * pathd, int(-dim / pathstep) * pathstep, 0))
|
||||
v.rotate(e)
|
||||
v += vm # shifting for the rotation, so pattern rotates around middle...
|
||||
|
@ -70,14 +70,14 @@ def getPathPatternParallel(o, angle):
|
|||
chunk.points.reverse()
|
||||
|
||||
if len(chunk.points) > 0:
|
||||
pathchunks.append(chunk)
|
||||
pathchunks.append(chunk.to_chunk())
|
||||
if len(pathchunks) > 1 and reverse and o.movement.parallel_step_back and not o.use_layers:
|
||||
# parallel step back - for finishing, best with climb movement, saves cutter life by going into
|
||||
# material with climb, while using move back on the surface to improve finish
|
||||
# (which would otherwise be a conventional move in the material)
|
||||
|
||||
if o.movement.type == 'CONVENTIONAL' or o.movement.type == 'CLIMB':
|
||||
pathchunks[-2].points.reverse()
|
||||
pathchunks[-2].reverse()
|
||||
changechunk = pathchunks[-1]
|
||||
pathchunks[-1] = pathchunks[-2]
|
||||
pathchunks[-2] = changechunk
|
||||
|
@ -125,6 +125,7 @@ def getPathPatternParallel(o, angle):
|
|||
chunks.append(nax.swapaxes(0, 1))
|
||||
# chunks
|
||||
pathchunks = []
|
||||
print("WOO")
|
||||
for ch in chunks:
|
||||
ch = ch.tolist()
|
||||
pathchunks.append(camPathChunk(ch))
|
||||
|
@ -160,7 +161,7 @@ def getPathPattern(operation):
|
|||
y = 0.0
|
||||
incx = 1
|
||||
incy = 0
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
i = 0
|
||||
while maxxp - minxp > 0 and maxyp - minyp > 0:
|
||||
|
||||
|
@ -206,10 +207,10 @@ def getPathPattern(operation):
|
|||
for si in range(0, len(chunk.points)):
|
||||
s = chunk.points[si]
|
||||
chunk.points[si] = (o.max.x + o.min.x - s[0], s[1], s[2])
|
||||
pathchunks = [chunk]
|
||||
pathchunks = [chunk.to_chunk()]
|
||||
|
||||
elif o.strategy == 'SPIRAL':
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
pathd = o.dist_between_paths
|
||||
pathstep = o.dist_along_paths
|
||||
midx = (o.max.x + o.min.x) / 2
|
||||
|
@ -234,21 +235,23 @@ def getPathPattern(operation):
|
|||
if o.max.x > midx + v.x > o.min.x and o.max.y > midy + v.y > o.min.y:
|
||||
chunk.points.append((midx + v.x, midy + v.y, zlevel))
|
||||
else:
|
||||
pathchunks.append(chunk)
|
||||
chunk = camPathChunk([])
|
||||
pathchunks.append(chunk.to_chunk())
|
||||
chunk = camPathChunkBuilder([])
|
||||
if len(chunk.points) > 0:
|
||||
pathchunks.append(chunk)
|
||||
pathchunks.append(chunk.to_chunk())
|
||||
if o.movement.insideout == 'OUTSIDEIN':
|
||||
pathchunks.reverse()
|
||||
for chunk in pathchunks:
|
||||
if o.movement.insideout == 'OUTSIDEIN':
|
||||
chunk.points.reverse()
|
||||
chunk.reverse()
|
||||
|
||||
if (o.movement.type == 'CONVENTIONAL' and o.movement.spindle_rotation == 'CW') or (
|
||||
o.movement.type == 'CLIMB' and o.movement.spindle_rotation == 'CCW'):
|
||||
for si in range(0, len(chunk.points)):
|
||||
s = chunk.points[si]
|
||||
chunk.points[si] = (o.max.x + o.min.x - s[0], s[1], s[2])
|
||||
##TODO
|
||||
chunk.flipX(o.max.x+o.min.x)
|
||||
# for si in range(0, len(chunk.points)):
|
||||
# s = chunk.points[si]
|
||||
# chunk.points[si] = (o.max.x + o.min.x - s[0], s[1], s[2])
|
||||
|
||||
elif o.strategy == 'CIRCLES':
|
||||
|
||||
|
@ -263,14 +266,14 @@ def getPathPattern(operation):
|
|||
# progress(x,y,midx,midy)
|
||||
e = Euler((0, 0, 0))
|
||||
pi = math.pi
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
chunk.points.append((midx, midy, zlevel))
|
||||
pathchunks.append(chunk)
|
||||
pathchunks.append(chunk.to_chunk())
|
||||
r = 0
|
||||
|
||||
while r < maxr:
|
||||
r += pathd
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
firstchunk = chunk
|
||||
v = Vector((-r, 0, 0))
|
||||
steps = 2 * pi * r / pathstep
|
||||
|
@ -286,18 +289,20 @@ def getPathPattern(operation):
|
|||
else:
|
||||
if len(chunk.points) > 0:
|
||||
chunk.closed = False
|
||||
chunk=chunk.to_chunk()
|
||||
pathchunks.append(chunk)
|
||||
currentstepchunks.append(chunk)
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
v.rotate(e)
|
||||
|
||||
if len(chunk.points) > 0:
|
||||
chunk.points.append(firstchunk.points[0])
|
||||
if chunk == firstchunk:
|
||||
chunk.closed = True
|
||||
chunk=chunk.to_chunk()
|
||||
pathchunks.append(chunk)
|
||||
currentstepchunks.append(chunk)
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
for ch in laststepchunks:
|
||||
for p in currentstepchunks:
|
||||
parentChildDist(p, ch, o)
|
||||
|
@ -306,13 +311,10 @@ def getPathPattern(operation):
|
|||
pathchunks.reverse()
|
||||
for chunk in pathchunks:
|
||||
if o.movement.insideout == 'OUTSIDEIN':
|
||||
chunk.points.reverse()
|
||||
chunk.reverse()
|
||||
if (o.movement.type == 'CONVENTIONAL' and o.movement.spindle_rotation == 'CW') or (
|
||||
o.movement.type == 'CLIMB' and o.movement.spindle_rotation == 'CCW'):
|
||||
chunk.points.reverse()
|
||||
# for si in range(0,len(chunk.points)):
|
||||
# s=chunk.points[si]
|
||||
# chunk.points[si]=(o.max.x+o.min.x-s[0],s[1],s[2])
|
||||
chunk.reverse()
|
||||
# pathchunks=sortChunks(pathchunks,o)not until they get hierarchy parents!
|
||||
elif o.strategy == 'OUTLINEFILL':
|
||||
|
||||
|
@ -379,10 +381,10 @@ def getPathPattern(operation):
|
|||
|
||||
for chunk in pathchunks:
|
||||
if o.movement.insideout == 'OUTSIDEIN':
|
||||
chunk.points.reverse()
|
||||
chunk.reverse()
|
||||
if (o.movement.type == 'CLIMB' and o.movement.spindle_rotation == 'CW') or (
|
||||
o.movement.type == 'CONVENTIONAL' and o.movement.spindle_rotation == 'CCW'):
|
||||
chunk.points.reverse()
|
||||
chunk.reverse()
|
||||
|
||||
chunksRefine(pathchunks, o)
|
||||
progress(time.time() - t)
|
||||
|
@ -436,7 +438,7 @@ def getPathPattern4axis(operation):
|
|||
if o.strategy4axis == 'PARALLELR':
|
||||
|
||||
for a in range(0, floor(steps) + 1):
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
|
||||
cutterstart[a1] = o.min[a1] + a * o.dist_between_paths
|
||||
cutterend[a1] = cutterstart[a1]
|
||||
|
@ -464,7 +466,7 @@ def getPathPattern4axis(operation):
|
|||
chunk.endpoints.append(chunk.endpoints[0])
|
||||
chunk.rotations.append(chunk.rotations[0])
|
||||
|
||||
pathchunks.append(chunk)
|
||||
pathchunks.append(chunk.to_chunk())
|
||||
|
||||
if o.strategy4axis == 'PARALLEL':
|
||||
circlesteps = (mradius * pi * 2) / o.dist_between_paths
|
||||
|
@ -478,7 +480,7 @@ def getPathPattern4axis(operation):
|
|||
reverse = False
|
||||
|
||||
for b in range(0, floor(circlesteps) + 1):
|
||||
chunk = camPathChunk([])
|
||||
chunk = camPathChunkBuilder([])
|
||||
cutterstart[a2] = 0
|
||||
cutterstart[a3] = radius
|
||||
|
||||
|
@ -500,7 +502,7 @@ def getPathPattern4axis(operation):
|
|||
chunk.rotations.append(rot)
|
||||
|
||||
chunk.depth = radiusend - radius
|
||||
pathchunks.append(chunk)
|
||||
pathchunks.append(chunk.to_chunk())
|
||||
|
||||
if (reverse and o.movement.type == 'MEANDER') or (
|
||||
o.movement.type == 'CONVENTIONAL' and o.movement.spindle_rotation == 'CW') or (
|
||||
|
@ -514,7 +516,7 @@ def getPathPattern4axis(operation):
|
|||
|
||||
a1step = o.dist_between_paths / circlesteps
|
||||
|
||||
chunk = camPathChunk([]) # only one chunk, init here
|
||||
chunk = camPathChunkBuilder([]) # only one chunk, init here
|
||||
|
||||
for a in range(0, floor(steps) + 1):
|
||||
|
||||
|
@ -540,7 +542,7 @@ def getPathPattern4axis(operation):
|
|||
|
||||
chunk.depth = radiusend - radius
|
||||
|
||||
pathchunks.append(chunk)
|
||||
pathchunks.append(chunk.to_chunk())
|
||||
# print(chunk.startpoints)
|
||||
# print(pathchunks)
|
||||
# sprint(len(pathchunks))
|
||||
|
|
|
@ -120,7 +120,7 @@ async def generateSimulationImage(operations, limits):
|
|||
resy = math.ceil(sy / simulation_detail) + 2 * borderwidth
|
||||
|
||||
# create array in which simulation happens, similar to an image to be painted in.
|
||||
si = np.full(shape=(resx,resy),fill_value=maxz,dtype=np.float)
|
||||
si = np.full(shape=(resx,resy),fill_value=maxz,dtype=float)
|
||||
|
||||
num_operations=len(operations)
|
||||
|
||||
|
@ -288,7 +288,7 @@ def getCutterArray(operation, pixsize):
|
|||
r = operation.cutter_diameter / 2 + operation.skin # /operation.pixsize
|
||||
res = math.ceil((r * 2) / pixsize)
|
||||
m = res / 2.0
|
||||
car = np.full(shape=(res,res),fill_value=-10.0,dtype=np.float)
|
||||
car = np.full(shape=(res,res),fill_value=-10.0,dtype=float)
|
||||
|
||||
v = mathutils.Vector((0, 0, 0))
|
||||
ps = pixsize
|
||||
|
|
|
@ -81,11 +81,12 @@ async def cutout(o):
|
|||
chunksFromCurve = []
|
||||
for ob in o.objects:
|
||||
chunksFromCurve.extend(curveToChunks(ob, o.use_modifiers))
|
||||
for ch in chunksFromCurve:
|
||||
# print(ch.points)
|
||||
# chunks always have polys now
|
||||
# for ch in chunksFromCurve:
|
||||
# # print(ch.points)
|
||||
|
||||
if len(ch.points) > 2:
|
||||
ch.poly = chunkToShapely(ch)
|
||||
# if len(ch.points) > 2:
|
||||
# ch.poly = chunkToShapely(ch)
|
||||
|
||||
# p.addContour(ch.poly)
|
||||
else:
|
||||
|
@ -122,12 +123,12 @@ async def cutout(o):
|
|||
if (o.movement.type == 'CLIMB' and o.movement.spindle_rotation == 'CCW') or (
|
||||
o.movement.type == 'CONVENTIONAL' and o.movement.spindle_rotation == 'CW'):
|
||||
for ch in chunksFromCurve:
|
||||
ch.points.reverse()
|
||||
ch.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()
|
||||
ch.reverse()
|
||||
|
||||
layers = getLayers(o, o.maxz, checkminz(o))
|
||||
extendorder = []
|
||||
|
@ -141,7 +142,7 @@ async def cutout(o):
|
|||
for layer in layers:
|
||||
chunk_copy = chunk.copy()
|
||||
if dir_switch:
|
||||
chunk_copy.points.reverse()
|
||||
chunk_copy.reverse()
|
||||
extendorder.append([chunk_copy, layer])
|
||||
if (not chunk.closed) and o.movement.type == "MEANDER":
|
||||
dir_switch = not dir_switch
|
||||
|
@ -264,12 +265,13 @@ async def proj_curve(s, o):
|
|||
extend_down = 0.04
|
||||
tsamples = curveToChunks(targetCurve)
|
||||
for chi, ch in enumerate(pathSamples):
|
||||
cht = tsamples[chi].points
|
||||
cht = tsamples[chi].get_points()
|
||||
ch.depth = 0
|
||||
for i, s in enumerate(ch.points):
|
||||
ch_points=ch.get_points()
|
||||
for i, s in enumerate(ch_points):
|
||||
# move the points a bit
|
||||
ep = Vector(cht[i])
|
||||
sp = Vector(ch.points[i])
|
||||
sp = Vector(ch_points[i])
|
||||
# extend startpoint
|
||||
vecs = sp - ep
|
||||
vecs.normalize()
|
||||
|
@ -288,8 +290,8 @@ async def proj_curve(s, o):
|
|||
|
||||
vec = sp - ep
|
||||
ch.depth = min(ch.depth, -vec.length)
|
||||
ch.points[i] = sp.copy()
|
||||
|
||||
ch_points[i] = sp.copy()
|
||||
ch.set_points(ch_points)
|
||||
layers = getLayers(o, 0, ch.depth)
|
||||
|
||||
chunks.extend(utils.sampleChunksNAxis(o, pathSamples, layers))
|
||||
|
@ -358,7 +360,7 @@ async def pocket(o):
|
|||
if (o.movement.type == 'CLIMB' and o.movement.spindle_rotation == 'CW') or (
|
||||
o.movement.type == 'CONVENTIONAL' and o.movement.spindle_rotation == 'CCW'):
|
||||
for ch in chunksFromCurve:
|
||||
ch.points.reverse()
|
||||
ch.reverse()
|
||||
|
||||
chunksFromCurve = await utils.sortChunks(chunksFromCurve, o)
|
||||
|
||||
|
@ -380,7 +382,7 @@ async def pocket(o):
|
|||
revheight = helix_circumference * tan(o.movement.ramp_in_angle)
|
||||
for chi, ch in enumerate(lchunks):
|
||||
if not chunksFromCurve[chi].children:
|
||||
p = ch.points[0] # TODO:intercept closest next point when it should stay low
|
||||
p = ch.get_point(0) # TODO:intercept closest next point when it should stay low
|
||||
# first thing to do is to check if helix enter can really enter.
|
||||
checkc = Circle(helix_radius + c_offset, o.optimisation.circle_detail)
|
||||
checkc = affinity.translate(checkc, p[0], p[1])
|
||||
|
@ -401,7 +403,9 @@ async def pocket(o):
|
|||
for v in h:
|
||||
nhelix.append((2 * p[0] - v[0], v[1], v[2]))
|
||||
h = nhelix
|
||||
ch.points = h + ch.points
|
||||
ch.extend(h,at_index=0)
|
||||
# ch.points = h + ch.points
|
||||
|
||||
else:
|
||||
o.info.warnings += 'Helix entry did not fit! \n '
|
||||
ch.closed = True
|
||||
|
@ -415,13 +419,13 @@ async def pocket(o):
|
|||
if chunksFromCurve[chi].parents == [] or len(chunksFromCurve[chi].parents) == 1:
|
||||
|
||||
revolutions = 0.25
|
||||
v1 = Vector(ch.points[-1])
|
||||
v1 = Vector(ch.get_point(-1))
|
||||
i = -2
|
||||
v2 = Vector(ch.points[i])
|
||||
v2 = Vector(ch.get_point(i))
|
||||
v = v1 - v2
|
||||
while v.length == 0:
|
||||
i = i - 1
|
||||
v2 = Vector(ch.points[i])
|
||||
v2 = Vector(ch.get_point(i))
|
||||
v = v1 - v2
|
||||
|
||||
v.normalize()
|
||||
|
@ -465,13 +469,13 @@ async def pocket(o):
|
|||
break
|
||||
|
||||
if covers:
|
||||
ch.points.extend(rothelix)
|
||||
ch.extend(rothelix)
|
||||
|
||||
chunks.extend(lchunks)
|
||||
|
||||
if o.movement.ramp:
|
||||
for ch in chunks:
|
||||
ch.rampZigZag(ch.zstart, ch.points[0][2], o)
|
||||
ch.rampZigZag(ch.zstart, ch.get_point(0)[2], o)
|
||||
|
||||
if o.first_down:
|
||||
if o.pocket_option == "OUTSIDE":
|
||||
|
@ -559,7 +563,7 @@ async def drill(o):
|
|||
for chunk in chunks:
|
||||
# If using object for minz then use z from points in object
|
||||
if o.minz_from == 'OBJECT':
|
||||
z = chunk.points[0][2]
|
||||
z = chunk.get_point(0)[2]
|
||||
else: # using operation minz
|
||||
z = o.minz
|
||||
# only add a chunk layer if the chunk z point is in or lower than the layer
|
||||
|
@ -626,16 +630,16 @@ async def medial_axis(o):
|
|||
ipol = 0
|
||||
for poly in polys.geoms:
|
||||
ipol = ipol + 1
|
||||
print("polygon:", ipol)
|
||||
schunks = shapelyToChunks(poly, -1)
|
||||
schunks = chunksRefineThreshold(schunks, o.medial_axis_subdivision,
|
||||
o.medial_axis_threshold) # chunksRefine(schunks,o)
|
||||
|
||||
verts = []
|
||||
for ch in schunks:
|
||||
for pt in ch.points:
|
||||
# pvoro = Site(pt[0], pt[1])
|
||||
verts.append(pt) # (pt[0], pt[1]), pt[2])
|
||||
verts.extend(ch.get_points())
|
||||
# for pt in ch.get_points():
|
||||
# # pvoro = Site(pt[0], pt[1])
|
||||
# verts.append(pt) # (pt[0], pt[1]), pt[2])
|
||||
# verts= points#[[vert.x, vert.y, vert.z] for vert in vertsPts]
|
||||
nDupli, nZcolinear = unique(verts)
|
||||
nVerts = len(verts)
|
||||
|
@ -831,12 +835,10 @@ def chunksToMesh(chunks, o):
|
|||
|
||||
for chi in range(0, len(chunks)):
|
||||
|
||||
# print(chi)
|
||||
|
||||
ch = chunks[chi]
|
||||
# print(chunks)
|
||||
# print (ch)
|
||||
if len(ch.points) > 0: # TODO: there is a case where parallel+layers+zigzag ramps send empty chunks here...
|
||||
if ch.count() > 0: # TODO: there is a case where parallel+layers+zigzag ramps send empty chunks here...
|
||||
# print(len(ch.points))
|
||||
nverts = []
|
||||
if o.optimisation.optimize:
|
||||
|
@ -847,14 +849,14 @@ def chunksToMesh(chunks, o):
|
|||
if lifted: # did the cutter lift before? if yes, put a new position above of the first point of next chunk.
|
||||
if o.machine_axes == '3' or (o.machine_axes == '5' and o.strategy5axis == 'INDEXED') or (
|
||||
o.machine_axes == '4' and o.strategy4axis == 'INDEXED'):
|
||||
v = (ch.points[0][0], ch.points[0][1], free_height)
|
||||
v = (ch.get_point(0)[0], ch.get_point(0)[1], free_height)
|
||||
else: # otherwise, continue with the next chunk without lifting/dropping
|
||||
v = ch.startpoints[0] # startpoints=retract points
|
||||
verts_rotations.append(ch.rotations[0])
|
||||
verts.append(v)
|
||||
|
||||
# add whole chunk
|
||||
verts.extend(ch.points)
|
||||
verts.extend(ch.get_points())
|
||||
|
||||
# add rotations for n-axis
|
||||
if o.machine_axes != '3':
|
||||
|
@ -862,10 +864,10 @@ def chunksToMesh(chunks, o):
|
|||
|
||||
lift = True
|
||||
# check if lifting should happen
|
||||
if chi < len(chunks) - 1 and len(chunks[chi + 1].points) > 0:
|
||||
if chi < len(chunks) - 1 and chunks[chi + 1].count() > 0:
|
||||
# TODO: remake this for n axis, and this check should be somewhere else...
|
||||
last = Vector(ch.points[-1])
|
||||
first = Vector(chunks[chi + 1].points[0])
|
||||
last = Vector(ch.get_point(-1))
|
||||
first = Vector(chunks[chi + 1].get_point(0))
|
||||
vect = first - last
|
||||
if (o.machine_axes == '3' and (o.strategy == 'PARALLEL' or o.strategy == 'CROSS')
|
||||
and vect.z == 0 and vect.length < o.dist_between_paths * 2.5) \
|
||||
|
@ -878,7 +880,7 @@ def chunksToMesh(chunks, o):
|
|||
if lift:
|
||||
if o.machine_axes == '3' or (o.machine_axes == '5' and o.strategy5axis == 'INDEXED') or (
|
||||
o.machine_axes == '4' and o.strategy4axis == 'INDEXED'):
|
||||
v = (ch.points[-1][0], ch.points[-1][1], free_height)
|
||||
v = (ch.get_point(-1)[0], ch.get_point(-1)[1], free_height)
|
||||
else:
|
||||
v = ch.startpoints[-1]
|
||||
verts_rotations.append(ch.rotations[-1])
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import bpy
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
warnings.simplefilter("once")
|
||||
|
||||
# Get the scene
|
||||
s = bpy.context.scene
|
||||
|
@ -12,3 +16,5 @@ for i, operation in enumerate(s.cam_operations):
|
|||
# Run the calculate_cam_path() operator
|
||||
bpy.ops.object.calculate_cam_path()
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@ import tempfile
|
|||
import sys
|
||||
import subprocess
|
||||
import pathlib
|
||||
import shutil
|
||||
|
||||
INSTALL_CODE=f"""
|
||||
import bpy
|
||||
bpy.ops.preferences.addon_install(filepath='{sys.argv[1]}')
|
||||
bpy.ops.preferences.addon_enable(module='cam')
|
||||
bpy.ops.wm.save_userpref()
|
||||
import cam
|
||||
"""
|
||||
|
||||
NUM_RETRIES=10
|
||||
|
@ -15,15 +17,20 @@ NUM_RETRIES=10
|
|||
with tempfile.TemporaryDirectory() as td:
|
||||
file=pathlib.Path(td,"install.py")
|
||||
file.write_text(INSTALL_CODE)
|
||||
command = f'blender -b -P "{str(file)}"'
|
||||
|
||||
# blender 4.0 installing addon crashes sometimes on mac github actions...
|
||||
for x in range(NUM_RETRIES):
|
||||
try:
|
||||
subprocess.run(command, shell=True, check=True,capture_output=True)
|
||||
subprocess.run([shutil.which('blender'),'-b','-P',str(file)], shell=False, check=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
|
||||
print("installed addon okay")
|
||||
sys.exit(0)
|
||||
except subprocess.CalledProcessError as e:
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("Install addon failed, retrying:",e)
|
||||
for line in e.stderr:
|
||||
print("Command output:")
|
||||
print("------------------------------")
|
||||
print(e.output)
|
||||
print("------------------------------")
|
||||
for line in str(e.output):
|
||||
if line.startswith("Writing: "):
|
||||
crash_file=pathlib.Path(line[len("Writing: "):])
|
||||
if crash_file.exists():
|
||||
|
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik binarny nie jest wyświetlany.
|
@ -0,0 +1,362 @@
|
|||
(Created with grbl post processor 2024/01/26 12:08)
|
||||
G21
|
||||
(G-code generated with BlenderCAM and NC library)
|
||||
G17G90
|
||||
(Tool: D = 3.0 mm type END flutes 2)
|
||||
S12000M03
|
||||
G00 Z10.0
|
||||
|
||||
G0X0Y0Z10
|
||||
X0.999Y2
|
||||
G1Z-5.1F500
|
||||
Y0.999F1000
|
||||
X-0.999
|
||||
Y-0.999
|
||||
X3.999
|
||||
Y3.999
|
||||
X-3.999
|
||||
Y-3.999
|
||||
X6.999
|
||||
Y6.999
|
||||
X-6.999
|
||||
Y-6.999
|
||||
X9.999
|
||||
Y9.999
|
||||
X-9.999
|
||||
Y-9.999
|
||||
X12.999
|
||||
Y12.999
|
||||
X-12.999
|
||||
Y-12.999
|
||||
X15.999
|
||||
Y15.999
|
||||
X-15.999
|
||||
Y-15.999
|
||||
X18.999
|
||||
Y18.999
|
||||
X-18.999
|
||||
Y-18.999
|
||||
X21.999
|
||||
Y21.999
|
||||
X-21.999
|
||||
Y-21.999
|
||||
X24.999
|
||||
Y24.999
|
||||
X-24.999
|
||||
Y-24.999
|
||||
X27.999
|
||||
Y27.999
|
||||
X-27.999
|
||||
Y-27.999
|
||||
X30.999
|
||||
Y30.999
|
||||
X-30.999
|
||||
Y-30.999
|
||||
X33.999
|
||||
Y33.999
|
||||
X-33.999
|
||||
Y-33.999
|
||||
X36.999
|
||||
Y36.999
|
||||
X-36.999
|
||||
Y-36.999
|
||||
X39.999
|
||||
Y39.999
|
||||
X-39.999
|
||||
Y-39.999
|
||||
X42.999
|
||||
Y42.999
|
||||
X-42.999
|
||||
Y-42.999
|
||||
X45.999
|
||||
Y45.999
|
||||
X-45.999
|
||||
Y-45.999
|
||||
X48.999
|
||||
Y47.5
|
||||
G0Z10
|
||||
X47.5Y48.999
|
||||
G1Z-5.1F500
|
||||
X-47.5F1000
|
||||
G0Z10
|
||||
X-48.999Y47.5
|
||||
G1Z-5.1F500
|
||||
Y-47.5F1000
|
||||
G0Z10
|
||||
X-47.5Y-48.999
|
||||
G1Z-5.1F500
|
||||
X47.5F1000
|
||||
G0Z10
|
||||
X51.999Y-44.5
|
||||
G1Z-5.1F500
|
||||
Y44.5F1000
|
||||
G0Z10
|
||||
X44.5Y51.999
|
||||
G1Z-5.1F500
|
||||
X-44.5F1000
|
||||
G0Z10
|
||||
X-51.999Y44.5
|
||||
G1Z-5.1F500
|
||||
Y-44.5F1000
|
||||
G0Z10
|
||||
X-44.5Y-51.999
|
||||
G1Z-5.1F500
|
||||
X44.5F1000
|
||||
G0Z10
|
||||
X54.999Y-40.5
|
||||
G1Z-5.1F500
|
||||
Y40.5F1000
|
||||
G0Z10
|
||||
X40.5Y54.999
|
||||
G1Z-5.1F500
|
||||
X-40.5F1000
|
||||
G0Z10
|
||||
X-54.999Y40.5
|
||||
G1Z-5.1F500
|
||||
Y-40.5F1000
|
||||
G0Z10
|
||||
X-40.5Y-54.999
|
||||
G1Z-5.1F500
|
||||
X40.5F1000
|
||||
G0Z10
|
||||
X57.999Y-36
|
||||
G1Z-5.1F500
|
||||
Y36F1000
|
||||
G0Z10
|
||||
X36Y57.999
|
||||
G1Z-5.1F500
|
||||
X-36F1000
|
||||
G0Z10
|
||||
X-57.999Y36
|
||||
G1Z-5.1F500
|
||||
Y-36F1000
|
||||
G0Z10
|
||||
X-36Y-57.999
|
||||
G1Z-5.1F500
|
||||
X36F1000
|
||||
G0Z10
|
||||
X60.999Y-31
|
||||
G1Z-5.1F500
|
||||
Y31F1000
|
||||
G0Z10
|
||||
X31Y60.999
|
||||
G1Z-5.1F500
|
||||
X-31F1000
|
||||
G0Z10
|
||||
X-60.999Y31
|
||||
G1Z-5.1F500
|
||||
Y-31F1000
|
||||
G0Z10
|
||||
X-31Y-60.999
|
||||
G1Z-5.1F500
|
||||
X31F1000
|
||||
G0Z10
|
||||
X63.999Y-24
|
||||
G1Z-5.1F500
|
||||
Y24F1000
|
||||
G0Z10
|
||||
X24Y63.999
|
||||
G1Z-5.1F500
|
||||
X-24F1000
|
||||
G0Z10
|
||||
X-63.999Y24
|
||||
G1Z-5.1F500
|
||||
Y-24F1000
|
||||
G0Z10
|
||||
X-24Y-63.999
|
||||
G1Z-5.1F500
|
||||
X24F1000
|
||||
G0Z10
|
||||
X67Y-14
|
||||
G1Z-5.1F500
|
||||
Y14F1000
|
||||
G0Z10
|
||||
X14Y67
|
||||
G1Z-5.1F500
|
||||
X-14F1000
|
||||
G0Z10
|
||||
X-67Y14
|
||||
G1Z-5.1F500
|
||||
Y-14F1000
|
||||
G0Z10
|
||||
X-14Y-67
|
||||
G1Z-5.1F500
|
||||
X14F1000
|
||||
G0Z10
|
||||
X0.999Y2
|
||||
G1Z-6.912F500
|
||||
Y0.999F1000
|
||||
X-0.999
|
||||
Y-0.999
|
||||
X3.999
|
||||
Y3.999
|
||||
X-3.999
|
||||
Y-3.999
|
||||
X6.999
|
||||
Y6.999
|
||||
X-6.999
|
||||
Y-6.999
|
||||
X9.999
|
||||
Y9.999
|
||||
X-9.999
|
||||
Y-9.999
|
||||
X12.999
|
||||
Y12.999
|
||||
X-12.999
|
||||
Y-12.999
|
||||
X15.999
|
||||
Y15.999
|
||||
X-15.999
|
||||
Y-15.999
|
||||
X18.999
|
||||
Y18.999
|
||||
X-18.999
|
||||
Y-18.999
|
||||
X21.999
|
||||
Y21.999
|
||||
X-21.999
|
||||
Y-21.999
|
||||
X24.999
|
||||
Y24.999
|
||||
X-24.999
|
||||
Y-24.999
|
||||
X27.999
|
||||
Y27.999
|
||||
X-27.999
|
||||
Y-27.999
|
||||
X30.999
|
||||
Y30.999
|
||||
X-30.999
|
||||
Y-30.999
|
||||
X33.999
|
||||
Y33.999
|
||||
X-33.999
|
||||
Y-33.999
|
||||
X36.999
|
||||
Y36.999
|
||||
X-36.999
|
||||
Y-36.999
|
||||
X39.999
|
||||
Y39.999
|
||||
X-39.999
|
||||
Y-39.999
|
||||
X42.999
|
||||
Y42.999
|
||||
X-42.999
|
||||
Y-42.999
|
||||
X45.999
|
||||
Y45.999
|
||||
X-45.999
|
||||
Y-45.999
|
||||
X48.999
|
||||
Y47.5
|
||||
G0Z10
|
||||
X47.5Y48.999
|
||||
G1Z-6.912F500
|
||||
X-47.5F1000
|
||||
G0Z10
|
||||
X-48.999Y47.5
|
||||
G1Z-6.912F500
|
||||
Y-47.5F1000
|
||||
G0Z10
|
||||
X-47.5Y-48.999
|
||||
G1Z-6.912F500
|
||||
X47.5F1000
|
||||
G0Z10
|
||||
X51.999Y-44.5
|
||||
G1Z-6.912F500
|
||||
Y44.5F1000
|
||||
G0Z10
|
||||
X44.5Y51.999
|
||||
G1Z-6.912F500
|
||||
X-44.5F1000
|
||||
G0Z10
|
||||
X-51.999Y44.5
|
||||
G1Z-6.912F500
|
||||
Y-44.5F1000
|
||||
G0Z10
|
||||
X-44.5Y-51.999
|
||||
G1Z-6.912F500
|
||||
X44.5F1000
|
||||
G0Z10
|
||||
X54.999Y-40.5
|
||||
G1Z-6.912F500
|
||||
Y40.5F1000
|
||||
G0Z10
|
||||
X40.5Y54.999
|
||||
G1Z-6.912F500
|
||||
X-40.5F1000
|
||||
G0Z10
|
||||
X-54.999Y40.5
|
||||
G1Z-6.912F500
|
||||
Y-40.5F1000
|
||||
G0Z10
|
||||
X-40.5Y-54.999
|
||||
G1Z-6.912F500
|
||||
X40.5F1000
|
||||
G0Z10
|
||||
X57.999Y-36
|
||||
G1Z-6.912F500
|
||||
Y36F1000
|
||||
G0Z10
|
||||
X36Y57.999
|
||||
G1Z-6.912F500
|
||||
X-36F1000
|
||||
G0Z10
|
||||
X-57.999Y36
|
||||
G1Z-6.912F500
|
||||
Y-36F1000
|
||||
G0Z10
|
||||
X-36Y-57.999
|
||||
G1Z-6.912F500
|
||||
X36F1000
|
||||
G0Z10
|
||||
X60.999Y-31
|
||||
G1Z-6.912F500
|
||||
Y31F1000
|
||||
G0Z10
|
||||
X31Y60.999
|
||||
G1Z-6.912F500
|
||||
X-31F1000
|
||||
G0Z10
|
||||
X-60.999Y31
|
||||
G1Z-6.912F500
|
||||
Y-31F1000
|
||||
G0Z10
|
||||
X-31Y-60.999
|
||||
G1Z-6.912F500
|
||||
X31F1000
|
||||
G0Z10
|
||||
X63.999Y-24
|
||||
G1Z-6.912F500
|
||||
Y24F1000
|
||||
G0Z10
|
||||
X24Y63.999
|
||||
G1Z-6.912F500
|
||||
X-24F1000
|
||||
G0Z10
|
||||
X-63.999Y24
|
||||
G1Z-6.912F500
|
||||
Y-24F1000
|
||||
G0Z10
|
||||
X-24Y-63.999
|
||||
G1Z-6.912F500
|
||||
X24F1000
|
||||
G0Z10
|
||||
X67Y-14
|
||||
G1Z-6.912F500
|
||||
Y14F1000
|
||||
G0Z10
|
||||
X14Y67
|
||||
G1Z-6.912F500
|
||||
X-14F1000
|
||||
G0Z10
|
||||
X-67Y14
|
||||
G1Z-6.912F500
|
||||
Y-14F1000
|
||||
G0Z10
|
||||
X-14Y-67
|
||||
G1Z-6.912F500
|
||||
X14F1000
|
||||
G0Z10
|
||||
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik binarny nie jest wyświetlany.
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,727 @@
|
|||
(Created with grbl post processor 2024/01/26 13:10)
|
||||
G21
|
||||
(G-code generated with BlenderCAM and NC library)
|
||||
G17G90
|
||||
(Tool: D = 3.0 mm type END flutes 2)
|
||||
S12000M03
|
||||
G00 Z10.0
|
||||
|
||||
G0X0Y0Z10
|
||||
X100.999Y102
|
||||
G1Z-0.1F500
|
||||
Y100.999Z-0.677
|
||||
X100.354Z-1.05F1000
|
||||
X100.999Z-1.422
|
||||
Y102Z-2F500
|
||||
Y100.999F1000
|
||||
X99
|
||||
Y99
|
||||
X103.999
|
||||
Y103.999
|
||||
X98.999
|
||||
X98.733Z-5.1F500
|
||||
X96F1000
|
||||
Y98.246
|
||||
Y98Z-2.501
|
||||
Y97.5Z-2
|
||||
Y96
|
||||
X106.999
|
||||
Y106.999
|
||||
X98.999
|
||||
X98.733Z-5.1F500
|
||||
X93F1000
|
||||
Y95.27
|
||||
Y95Z-2
|
||||
Y93
|
||||
X109.999
|
||||
Y109.999
|
||||
X98.499
|
||||
X98.233Z-5.1F500
|
||||
X90F1000
|
||||
Y94.273
|
||||
Y94Z-2
|
||||
Y90
|
||||
X112.999
|
||||
Y98
|
||||
Y98.255Z-5.1F500
|
||||
Y112.999F1000
|
||||
X112.51
|
||||
X111.999Z-2
|
||||
X96.999
|
||||
X96.732Z-5.1F500
|
||||
X87F1000
|
||||
Y93.775
|
||||
Y93.5Z-2
|
||||
Y87
|
||||
X115.999
|
||||
Y95.5
|
||||
Y95.752Z-5.1F500
|
||||
Y115.999F1000
|
||||
X115.505
|
||||
X115Z-2
|
||||
X93.999
|
||||
X93.729Z-5.1F500
|
||||
X84F1000
|
||||
Y93.778
|
||||
Y93.5Z-2
|
||||
Y84
|
||||
X118.999
|
||||
Y94
|
||||
Y94.25Z-5.1F500
|
||||
Y117.749F1000
|
||||
Y118Z-2
|
||||
Y118.999
|
||||
X81
|
||||
Y117.5
|
||||
Y117.218Z-5.1F500
|
||||
Y94.781F1000
|
||||
Y94.5Z-2
|
||||
Y81
|
||||
X121.999
|
||||
Y93.5
|
||||
Y93.748Z-5.1F500
|
||||
Y118.251F1000
|
||||
Y118.5Z-2
|
||||
Y121.999
|
||||
X78
|
||||
Y115.5
|
||||
Y115.216Z-5.1F500
|
||||
Y96.783F1000
|
||||
Y96.5Z-2
|
||||
Y78
|
||||
X125
|
||||
Y93.5
|
||||
Y93.746Z-5.1F500
|
||||
Y118.253F1000
|
||||
Y118.5Z-2
|
||||
Y125
|
||||
X75
|
||||
Y111.5
|
||||
Y111.213Z-5.1F500
|
||||
Y100.786F1000
|
||||
Y100.5Z-2
|
||||
Y75
|
||||
X127.999
|
||||
Y94.5
|
||||
Y94.744Z-5.1F500
|
||||
Y117.255F1000
|
||||
Y117.5Z-2
|
||||
Y127.999
|
||||
X72
|
||||
Y72
|
||||
X130.999
|
||||
Y96.5
|
||||
Y96.742Z-5.1F500
|
||||
Y115.257F1000
|
||||
Y115.5Z-2
|
||||
Y130.999
|
||||
X69
|
||||
Y69
|
||||
X134
|
||||
Y100
|
||||
Y100.5Z-3.952F500
|
||||
Y100.627Z-5.1
|
||||
Y111.372F1000
|
||||
Y111.5Z-3.951
|
||||
Y112Z-2
|
||||
Y134
|
||||
X66
|
||||
Y66
|
||||
X136.999
|
||||
Y136.999
|
||||
X63
|
||||
Y63
|
||||
X140
|
||||
Y140
|
||||
X60
|
||||
Y113.5
|
||||
Y113.198Z-5.1F500
|
||||
Y98.801F1000
|
||||
Y98.5Z-2
|
||||
Y60
|
||||
X78.499
|
||||
X78.782Z-5.1F500
|
||||
X93.729F1000
|
||||
X93.999Z-2
|
||||
X115
|
||||
X115.253Z-5.1F500
|
||||
X130.256F1000
|
||||
X130.5Z-2
|
||||
X142.999
|
||||
Y142.999
|
||||
X57
|
||||
Y116.5
|
||||
Y116.195Z-5.1F500
|
||||
Y95.804F1000
|
||||
Y95.5Z-2
|
||||
Y60.5
|
||||
Y60.195Z-5.1F500
|
||||
Y57F1000
|
||||
X60.198
|
||||
X60.499Z-2
|
||||
X75.999
|
||||
X76.285Z-5.1F500
|
||||
X96.732F1000
|
||||
X96.999Z-2
|
||||
X111.999
|
||||
X112.255Z-5.1F500
|
||||
X133.258F1000
|
||||
X133.499Z-2
|
||||
X145.999
|
||||
Y145.999
|
||||
X54
|
||||
Y118
|
||||
Y117.692Z-5.1F500
|
||||
Y94.307F1000
|
||||
Y94Z-2
|
||||
Y62
|
||||
Y61.692Z-5.1F500
|
||||
Y54F1000
|
||||
X61.7
|
||||
X61.999Z-2
|
||||
X74.499
|
||||
X74.786Z-5.1F500
|
||||
X98.233F1000
|
||||
X98.499Z-2
|
||||
X110.5
|
||||
X110.756Z-5.1F500
|
||||
X134.759F1000
|
||||
X135Z-2
|
||||
X147
|
||||
X147.232Z-5.1F500
|
||||
X149F1000
|
||||
Y57.268
|
||||
Y57.5Z-2
|
||||
Y98.5
|
||||
Y98.731Z-5.1F500
|
||||
Y113.268F1000
|
||||
Y113.5Z-2
|
||||
Y149
|
||||
X51
|
||||
Y118.5
|
||||
Y118.189Z-5.1F500
|
||||
Y93.81F1000
|
||||
Y93.5Z-2
|
||||
Y62.5
|
||||
Y62.189Z-5.1F500
|
||||
Y51F1000
|
||||
X62.201
|
||||
X62.499Z-2
|
||||
X73.5
|
||||
X73.787Z-5.1F500
|
||||
X98.733F1000
|
||||
X98.999Z-2
|
||||
X109.999
|
||||
X110.257Z-5.1F500
|
||||
X135.26F1000
|
||||
X135.499Z-2
|
||||
X146.5
|
||||
X146.732Z-5.1F500
|
||||
X151.999F1000
|
||||
Y60.27
|
||||
Y60.5Z-2
|
||||
Y95.5
|
||||
Y95.729Z-5.1F500
|
||||
Y116.27F1000
|
||||
Y116.5Z-2
|
||||
Y151.5
|
||||
Y151.729Z-5.1F500
|
||||
Y151.999F1000
|
||||
X151.458
|
||||
X151Z-2
|
||||
X130.5
|
||||
X130.256Z-5.1F500
|
||||
X115.253F1000
|
||||
X115Z-2
|
||||
X93.999
|
||||
X93.729Z-5.1F500
|
||||
X78.782F1000
|
||||
X78.499Z-2
|
||||
X57.499
|
||||
X57.195Z-5.1F500
|
||||
X48F1000
|
||||
Y149.813
|
||||
Y149.5Z-2
|
||||
Y118.5
|
||||
Y118.186Z-5.1F500
|
||||
Y93.813F1000
|
||||
Y93.5Z-2
|
||||
Y62.5
|
||||
Y62.186Z-5.1F500
|
||||
Y48F1000
|
||||
X62.201
|
||||
X62.499Z-2
|
||||
X73.999
|
||||
X74.286Z-5.1F500
|
||||
X98.733F1000
|
||||
X98.999Z-2
|
||||
X109.999
|
||||
X110.257Z-5.1F500
|
||||
X135.26F1000
|
||||
X135.499Z-2
|
||||
X146.5
|
||||
X146.732Z-5.1F500
|
||||
X155F1000
|
||||
Y61.772
|
||||
Y62Z-2
|
||||
Y94
|
||||
Y94.227Z-5.1F500
|
||||
Y117.772F1000
|
||||
Y118Z-2
|
||||
Y150
|
||||
Y150.227Z-5.1F500
|
||||
Y155F1000
|
||||
X148.731
|
||||
X148.499Z-2
|
||||
X133.499
|
||||
X133.258Z-5.1F500
|
||||
X112.255F1000
|
||||
X111.999Z-2
|
||||
X96.999
|
||||
X96.732Z-5.1F500
|
||||
X76.285F1000
|
||||
X75.999Z-2
|
||||
X60.499
|
||||
X60.198Z-5.1F500
|
||||
X45F1000
|
||||
Y150.817
|
||||
Y150.5Z-2
|
||||
Y117.5
|
||||
Y117.182Z-5.1F500
|
||||
Y94.817F1000
|
||||
Y94.5Z-2
|
||||
Y61.5
|
||||
Y61.182Z-5.1F500
|
||||
Y45F1000
|
||||
X61.199
|
||||
X61.499Z-2
|
||||
X74.499
|
||||
X74.786Z-5.1F500
|
||||
X97.732F1000
|
||||
X97.999Z-2
|
||||
X111
|
||||
X111.256Z-5.1F500
|
||||
X134.259F1000
|
||||
X134.499Z-2
|
||||
X147.499
|
||||
X147.731Z-5.1F500
|
||||
X157.999F1000
|
||||
Y62.274
|
||||
Y62.5Z-2
|
||||
Y93.5
|
||||
Y93.725Z-5.1F500
|
||||
Y118.274F1000
|
||||
Y118.5Z-2
|
||||
Y149.5
|
||||
Y149.725Z-5.1F500
|
||||
Y157.999F1000
|
||||
X147.232
|
||||
X147Z-2
|
||||
X135
|
||||
X134.759Z-5.1F500
|
||||
X110.756F1000
|
||||
X110.5Z-2
|
||||
X98.499
|
||||
X98.233Z-5.1F500
|
||||
X74.786F1000
|
||||
X74.499Z-2
|
||||
X61.999
|
||||
X61.7Z-5.1F500
|
||||
X42F1000
|
||||
Y152.32
|
||||
Y152Z-2
|
||||
Y116
|
||||
Y115.679Z-5.1F500
|
||||
Y96.32F1000
|
||||
Y96Z-2
|
||||
Y60
|
||||
Y59.679Z-5.1F500
|
||||
Y42F1000
|
||||
X59.698
|
||||
X59.999Z-2
|
||||
X76.499
|
||||
X76.784Z-5.1F500
|
||||
X95.753F1000
|
||||
X96Z-2.502
|
||||
X96.499Z-2
|
||||
X112.999
|
||||
X113.254Z-5.1F500
|
||||
X132.258F1000
|
||||
X132.499Z-2
|
||||
X149.499
|
||||
X149.73Z-5.1F500
|
||||
X160.999F1000
|
||||
Y62.275
|
||||
Y62.5Z-2
|
||||
Y93.5
|
||||
Y93.724Z-5.1F500
|
||||
Y118.275F1000
|
||||
Y118.5Z-2
|
||||
Y149.5
|
||||
Y149.724Z-5.1F500
|
||||
Y160.999F1000
|
||||
X146.732
|
||||
X146.5Z-2
|
||||
X135.499
|
||||
X135.26Z-5.1F500
|
||||
X110.257F1000
|
||||
X109.999Z-2
|
||||
X98.999
|
||||
X98.733Z-5.1F500
|
||||
X73.787F1000
|
||||
X73.5Z-2
|
||||
X62.499
|
||||
X62.201Z-5.1F500
|
||||
X39F1000
|
||||
Y156.324
|
||||
Y156Z-2
|
||||
Y112
|
||||
Y111.675Z-5.1F500
|
||||
Y100.324F1000
|
||||
Y100Z-2
|
||||
Y56
|
||||
Y55.675Z-5.1F500
|
||||
Y44.324F1000
|
||||
Y44Z-2
|
||||
Y39
|
||||
X43.999
|
||||
X44.317Z-5.1F500
|
||||
X55.694F1000
|
||||
X55.999Z-2
|
||||
X79.999
|
||||
X80.281Z-5.1F500
|
||||
X92.228F1000
|
||||
X92.5Z-2
|
||||
X116.499
|
||||
X116.752Z-5.1F500
|
||||
X128.755F1000
|
||||
X128.999Z-2
|
||||
X152.999
|
||||
X153.228Z-5.1F500
|
||||
X164F1000
|
||||
Y61.752
|
||||
Y62Z-2
|
||||
Y94
|
||||
Y94.247Z-5.1F500
|
||||
Y117.752F1000
|
||||
Y118Z-2
|
||||
Y150
|
||||
Y150.247Z-5.1F500
|
||||
Y164F1000
|
||||
X146.732
|
||||
X146.5Z-2
|
||||
X135.499
|
||||
X135.26Z-5.1F500
|
||||
X110.257F1000
|
||||
X109.999Z-2
|
||||
X98.999
|
||||
X98.733Z-5.1F500
|
||||
X74.286F1000
|
||||
X73.999Z-2
|
||||
X62.499
|
||||
X62.201Z-5.1F500
|
||||
X37.825F1000
|
||||
X37.499Z-2
|
||||
X36
|
||||
Y36
|
||||
X166.999
|
||||
Y40
|
||||
Y40.22Z-5.1F500
|
||||
Y59.779F1000
|
||||
Y60Z-2
|
||||
Y96
|
||||
Y96.22Z-5.1F500
|
||||
Y115.779F1000
|
||||
Y116Z-2
|
||||
Y152
|
||||
Y152.22Z-5.1F500
|
||||
Y166.999F1000
|
||||
X147.731
|
||||
X147.499Z-2
|
||||
X134.499
|
||||
X134.259Z-5.1F500
|
||||
X111.256F1000
|
||||
X111Z-2
|
||||
X97.999
|
||||
X97.732Z-5.1F500
|
||||
X74.786F1000
|
||||
X74.499Z-2
|
||||
X61.499
|
||||
X61.199Z-5.1F500
|
||||
X38.824F1000
|
||||
X38.499Z-2
|
||||
X33
|
||||
Y33
|
||||
X170
|
||||
Y43.5
|
||||
Y43.719Z-5.1F500
|
||||
Y56.28F1000
|
||||
Y56.5Z-2
|
||||
Y99.5
|
||||
Y99.719Z-5.1F500
|
||||
Y112.28F1000
|
||||
Y112.5Z-2
|
||||
Y155.5
|
||||
Y155.719Z-5.1F500
|
||||
Y168.28F1000
|
||||
Y168.5Z-2
|
||||
Y170
|
||||
X169
|
||||
X168.779Z-5.1F500
|
||||
X149.73F1000
|
||||
X149.499Z-2
|
||||
X132.499
|
||||
X132.258Z-5.1F500
|
||||
X113.254F1000
|
||||
X112.999Z-2
|
||||
X96.499
|
||||
X96Z-2.502F500
|
||||
X95.753Z-5.1
|
||||
X76.784F1000
|
||||
X76.499Z-2
|
||||
X59.999
|
||||
X59.698Z-5.1F500
|
||||
X40.322F1000
|
||||
X39.999Z-2
|
||||
X30
|
||||
Y30
|
||||
X173
|
||||
Y173
|
||||
X165.5
|
||||
X165.278Z-5.1F500
|
||||
X153.228F1000
|
||||
X152.999Z-2
|
||||
X128.999
|
||||
X128.755Z-5.1F500
|
||||
X116.752F1000
|
||||
X116.499Z-2
|
||||
X92.5
|
||||
X92.228Z-5.1F500
|
||||
X80.281F1000
|
||||
X79.999Z-2
|
||||
X55.999
|
||||
X55.694Z-5.1F500
|
||||
X44.317F1000
|
||||
X43.999Z-2
|
||||
X27
|
||||
Y27
|
||||
X175.999
|
||||
Y175.999
|
||||
X24
|
||||
Y24
|
||||
X179
|
||||
Y179
|
||||
X21
|
||||
Y21
|
||||
X181.999
|
||||
Y181.999
|
||||
X18
|
||||
Y18
|
||||
X185
|
||||
Y185
|
||||
X15
|
||||
Y15
|
||||
X188
|
||||
Y188
|
||||
X12
|
||||
Y12
|
||||
X191
|
||||
Y191
|
||||
X9
|
||||
Y9
|
||||
X194
|
||||
Y194
|
||||
X6
|
||||
Y6
|
||||
X196.999
|
||||
Y196.999
|
||||
X3
|
||||
Y3
|
||||
X198.5
|
||||
X196.854Z-1.05
|
||||
X198.5Z-0.1
|
||||
G0Z10
|
||||
X96.732Y112.999
|
||||
G1Z-5.1F500
|
||||
X96.499Z-7.786
|
||||
X87Z-7.62F1000
|
||||
Y94
|
||||
Y93.775Z-5.1
|
||||
Y98.105Z-2.6
|
||||
Y93.775Z-0.1
|
||||
G0Z10
|
||||
X125Y93.746
|
||||
G1Z-5.1F500
|
||||
Y94Z-8.283
|
||||
Y118F1000
|
||||
Y118.253Z-5.1
|
||||
Y113.923Z-2.6
|
||||
Y118.253Z-0.1
|
||||
G0Z10
|
||||
X134Y100.627
|
||||
G1Z-5.1F500
|
||||
Y101Z-8.44
|
||||
Y111F1000
|
||||
Y111.372Z-5.1
|
||||
Y107.041Z-2.6
|
||||
Y111.372Z-0.1
|
||||
G0Z10
|
||||
X60Y113.198
|
||||
G1Z-5.1F500
|
||||
Y113Z-7.149
|
||||
Y99F1000
|
||||
Y98.801Z-5.1
|
||||
Y103.131Z-2.6
|
||||
Y98.801Z-0.1
|
||||
G0Z10
|
||||
X76.285Y57
|
||||
G1Z-5.1F500
|
||||
X76.499Z-7.437
|
||||
X96.499Z-7.786F1000
|
||||
X96.732Z-5.1
|
||||
X92.401Z-2.6
|
||||
X96.732Z-0.1
|
||||
G0Z10
|
||||
X112.255
|
||||
G1Z-5.1F500
|
||||
X112.499Z-8.065
|
||||
X133Z-8.423F1000
|
||||
X133.258Z-5.1
|
||||
X128.928Z-2.6
|
||||
X133.258Z-0.1
|
||||
G0Z10
|
||||
X149Y98.731
|
||||
G1Z-5.1F500
|
||||
Y99Z-8.702
|
||||
Y113F1000
|
||||
Y113.268Z-5.1
|
||||
Y108.938Z-2.6
|
||||
Y113.268Z-0.1
|
||||
G0Z10
|
||||
X48Y118.186
|
||||
G1Z-5.1F500
|
||||
Y118Z-6.939
|
||||
Y94F1000
|
||||
Y93.813Z-5.1
|
||||
Y98.143Z-2.6
|
||||
Y93.813Z-0.1
|
||||
G0Z10
|
||||
Y62.186
|
||||
G1Z-5.1F500
|
||||
Y62Z-6.939
|
||||
Y48F1000
|
||||
X61.999Z-7.184
|
||||
X62.201Z-5.1
|
||||
X57.87Z-2.6
|
||||
X62.201Z-0.1
|
||||
G0Z10
|
||||
X96.732Y155
|
||||
G1Z-5.1F500
|
||||
X96.499Z-7.786
|
||||
X76.499Z-7.437F1000
|
||||
X76.285Z-5.1
|
||||
X80.615Z-2.6
|
||||
X76.285Z-0.1
|
||||
G0Z10
|
||||
X60.198
|
||||
G1Z-5.1F500
|
||||
X59.999Z-7.149
|
||||
X45Z-6.887F1000
|
||||
Y151
|
||||
Y150.817Z-5.1
|
||||
Y155Z-2.685
|
||||
X45.147Z-2.6
|
||||
X45Z-2.514
|
||||
Y150.817Z-0.1
|
||||
G0Z10
|
||||
Y117.182
|
||||
G1Z-5.1F500
|
||||
Y117Z-6.887
|
||||
Y95F1000
|
||||
Y94.817Z-5.1
|
||||
Y99.147Z-2.6
|
||||
Y94.817Z-0.1
|
||||
G0Z10
|
||||
Y61.182
|
||||
G1Z-5.1F500
|
||||
Y61Z-6.887
|
||||
Y45F1000
|
||||
X60.999Z-7.166
|
||||
X61.199Z-5.1
|
||||
X56.869Z-2.6
|
||||
X61.199Z-0.1
|
||||
G0Z10
|
||||
X147.731
|
||||
G1Z-5.1F500
|
||||
X148Z-8.685
|
||||
X157.999Z-8.859F1000
|
||||
Y62
|
||||
Y62.274Z-5.1
|
||||
Y57.943Z-2.6
|
||||
Y62.274Z-0.1
|
||||
G0Z10
|
||||
X80.281Y39
|
||||
G1Z-5.1F500
|
||||
X80.499Z-7.506
|
||||
X92Z-7.707F1000
|
||||
X92.228Z-5.1
|
||||
X87.898Z-2.6
|
||||
X92.228Z-0.1
|
||||
G0Z10
|
||||
X97.732Y166.999
|
||||
G1Z-5.1F500
|
||||
X97.499Z-7.803
|
||||
X74.999Z-7.41F1000
|
||||
X74.786Z-5.1
|
||||
X79.116Z-2.6
|
||||
X74.786Z-0.1
|
||||
G0Z10
|
||||
X61.199
|
||||
G1Z-5.1F500
|
||||
X60.999Z-7.166
|
||||
X38.999Z-6.782F1000
|
||||
X38.824Z-5.1
|
||||
X43.154Z-2.6
|
||||
X38.824Z-0.1
|
||||
G0Z10
|
||||
X170Y43.719
|
||||
G1Z-5.1F500
|
||||
Y44Z-9.069
|
||||
Y56F1000
|
||||
Y56.28Z-5.1
|
||||
Y51.95Z-2.6
|
||||
Y56.28Z-0.1
|
||||
G0Z10
|
||||
Y99.719
|
||||
G1Z-5.1F500
|
||||
Y100Z-9.069
|
||||
Y112F1000
|
||||
Y112.28Z-5.1
|
||||
Y107.95Z-2.6
|
||||
Y112.28Z-0.1
|
||||
G0Z10
|
||||
Y155.719
|
||||
G1Z-5.1F500
|
||||
Y156Z-9.069
|
||||
Y168F1000
|
||||
Y168.28Z-5.1
|
||||
Y163.95Z-2.6
|
||||
Y168.28Z-0.1
|
||||
G0Z10
|
||||
X132.258Y170
|
||||
G1Z-5.1F500
|
||||
X131.999Z-8.405
|
||||
X113.499Z-8.082F1000
|
||||
X113.254Z-5.1
|
||||
X117.584Z-2.6
|
||||
X113.254Z-0.1
|
||||
G0Z10
|
||||
X59.698
|
||||
G1Z-5.1F500
|
||||
X59.499Z-7.14
|
||||
X40.499Z-6.808F1000
|
||||
X40.322Z-5.1
|
||||
X44.652Z-2.6
|
||||
X40.322Z-0.1
|
||||
G0Z10
|
||||
|
Plik binarny nie jest wyświetlany.
|
@ -1,4 +1,4 @@
|
|||
(Created with grbl post processor 2024/01/13 06:54)
|
||||
(Created with grbl post processor 2024/01/26 12:15)
|
||||
G21
|
||||
(G-code generated with BlenderCAM and NC library)
|
||||
G17G90
|
||||
|
@ -976,7 +976,6 @@ G0Z10
|
|||
X-18.613Y-50.677
|
||||
G1Z-5F500
|
||||
X-18.091Y-50.524F1000
|
||||
X-18.063Y-50.517
|
||||
X-17.786Y-50.454
|
||||
X-17.806Y-50.438
|
||||
X-17.858Y-50.408
|
||||
|
@ -1105,7 +1104,6 @@ G0Z10
|
|||
X67.823Y80.439
|
||||
G1Z-5F500
|
||||
X69.398Y79.084F1000
|
||||
X69.414Y79.07
|
||||
X70.808Y77.65
|
||||
X70.823Y77.632
|
||||
X72.028Y76.153
|
||||
|
@ -1129,7 +1127,7 @@ X74.3Y56.047
|
|||
X73.85Y54.026
|
||||
X73.341Y52.119
|
||||
X72.773Y50.326
|
||||
X72.15Y48.66
|
||||
X72.144Y48.647
|
||||
X71.463Y47.096
|
||||
X71.457Y47.082
|
||||
X71.45Y47.068
|
||||
|
@ -1192,12 +1190,10 @@ X49.017Y-15.151
|
|||
X49.005Y-15.166
|
||||
X48.994Y-15.18
|
||||
X46.245Y-18.424
|
||||
X43.073Y-21.715
|
||||
X43.052Y-21.735
|
||||
X43.063Y-21.725
|
||||
X39.491Y-25.031
|
||||
X35.52Y-28.356
|
||||
X31.149Y-31.698
|
||||
X31.124Y-31.715
|
||||
X29.598Y-32.7
|
||||
X27.959Y-33.789
|
||||
X26.202Y-34.986
|
||||
|
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik binarny nie jest wyświetlany.
|
@ -51,7 +51,8 @@ class BlenderCAMTest(unittest.TestCase):
|
|||
return ''.join(list(diff)[:num_lines])
|
||||
|
||||
def execute_blender(self, blend_file):
|
||||
command = f'blender -b "{blend_file}" -P "{self.generator_path}"'
|
||||
command = f'blender -noaudio -b "{blend_file}" -P "{self.generator_path}"'
|
||||
print(f"Executing: {command}")
|
||||
subprocess.run(command, shell=True, check=True)
|
||||
|
||||
def run_test_case(self, test_case):
|
||||
|
|
|
@ -164,7 +164,7 @@ class CAM_MOVEMENT_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
self.layout.prop(self.op.movement, 'ramp_in_angle')
|
||||
self.layout.prop(self.op.movement, 'ramp_out')
|
||||
if self.op.movement.ramp_out:
|
||||
self.layout.prop(self.movement, 'ramp_out_angle')
|
||||
self.layout.prop(self.op.movement, 'ramp_out_angle')
|
||||
|
||||
def draw_retract_tangential(self):
|
||||
if not self.has_correct_level(): return
|
||||
|
|
|
@ -362,22 +362,22 @@ def getBoundsMultiple(operations):
|
|||
|
||||
|
||||
def samplePathLow(o, ch1, ch2, dosample):
|
||||
v1 = Vector(ch1.points[-1])
|
||||
v2 = Vector(ch2.points[0])
|
||||
v1 = Vector(ch1.get_point(-1))
|
||||
v2 = Vector(ch2.get_point(0))
|
||||
|
||||
v = v2 - v1
|
||||
d = v.length
|
||||
v.normalize()
|
||||
|
||||
vref = Vector((0, 0, 0))
|
||||
bpath = camPathChunk([])
|
||||
bpath_points = []
|
||||
i = 0
|
||||
while vref.length < d:
|
||||
i += 1
|
||||
vref = v * o.dist_along_paths * i
|
||||
if vref.length < d:
|
||||
p = v1 + vref
|
||||
bpath.points.append([p.x, p.y, p.z])
|
||||
bpath_points.append([p.x, p.y, p.z])
|
||||
# print('between path')
|
||||
# print(len(bpath))
|
||||
pixsize = o.optimisation.pixsize
|
||||
|
@ -389,18 +389,18 @@ def samplePathLow(o, ch1, ch2, dosample):
|
|||
o.update_bullet_collision_tag = False
|
||||
|
||||
cutterdepth = o.cutter_shape.dimensions.z / 2
|
||||
for p in bpath.points:
|
||||
for p in bpath_points:
|
||||
z = getSampleBullet(o.cutter_shape, p[0], p[1], cutterdepth, 1, o.minz)
|
||||
if z > p[2]:
|
||||
p[2] = z
|
||||
else:
|
||||
for p in bpath.points:
|
||||
for p in bpath_points:
|
||||
xs = (p[0] - o.min.x) / pixsize + o.borderwidth + pixsize / 2 # -m
|
||||
ys = (p[1] - o.min.y) / pixsize + o.borderwidth + pixsize / 2 # -m
|
||||
z = getSampleImage((xs, ys), o.offset_image, o.minz) + o.skin
|
||||
if z > p[2]:
|
||||
p[2] = z
|
||||
return bpath
|
||||
return camPathChunk(bpath_points)
|
||||
|
||||
|
||||
# def threadedSampling():#not really possible at all without running more blenders for same operation :( python!
|
||||
|
@ -424,7 +424,7 @@ async def sampleChunks(o, pathSamples, layers):
|
|||
cutterdepth = cutter.dimensions.z / 2
|
||||
else:
|
||||
if o.strategy != 'WATERLINE': # or prepare offset image, but not in some strategies.
|
||||
prepareArea(o)
|
||||
await prepareArea(o)
|
||||
|
||||
pixsize = o.optimisation.pixsize
|
||||
|
||||
|
@ -438,7 +438,7 @@ async def sampleChunks(o, pathSamples, layers):
|
|||
|
||||
totlen = 0 # total length of all chunks, to estimate sampling time.
|
||||
for ch in pathSamples:
|
||||
totlen += len(ch.points)
|
||||
totlen += ch.count()
|
||||
layerchunks = []
|
||||
minz = o.minz - 0.000001 # correction for image method problems
|
||||
layeractivechunks = []
|
||||
|
@ -446,7 +446,7 @@ async def sampleChunks(o, pathSamples, layers):
|
|||
|
||||
for l in layers:
|
||||
layerchunks.append([])
|
||||
layeractivechunks.append(camPathChunk([]))
|
||||
layeractivechunks.append(camPathChunkBuilder([]))
|
||||
lastrunchunks.append([])
|
||||
|
||||
zinvert = 0
|
||||
|
@ -473,7 +473,7 @@ async def sampleChunks(o, pathSamples, layers):
|
|||
|
||||
# for t in range(0,threads):
|
||||
|
||||
for s in patternchunk.points:
|
||||
for s in patternchunk.get_points():
|
||||
if o.strategy != 'WATERLINE' and int(100 * n / totlen) != last_percent:
|
||||
last_percent = int(100 * n / totlen)
|
||||
await progress_async('sampling paths ', last_percent)
|
||||
|
@ -583,17 +583,20 @@ async def sampleChunks(o, pathSamples, layers):
|
|||
|
||||
if terminatechunk:
|
||||
if len(ch.points) > 0:
|
||||
layerchunks[i].append(ch)
|
||||
thisrunchunks[i].append(ch)
|
||||
layeractivechunks[i] = camPathChunk([])
|
||||
as_chunk=ch.to_chunk()
|
||||
layerchunks[i].append(as_chunk)
|
||||
thisrunchunks[i].append(as_chunk)
|
||||
layeractivechunks[i] = camPathChunkBuilder([])
|
||||
lastsample = newsample
|
||||
|
||||
|
||||
for i, l in enumerate(layers):
|
||||
ch = layeractivechunks[i]
|
||||
if len(ch.points) > 0:
|
||||
layerchunks[i].append(ch)
|
||||
thisrunchunks[i].append(ch)
|
||||
layeractivechunks[i] = camPathChunk([])
|
||||
as_chunk=ch.to_chunk()
|
||||
layerchunks[i].append(as_chunk)
|
||||
thisrunchunks[i].append(as_chunk)
|
||||
layeractivechunks[i] = camPathChunkBuilder([])
|
||||
|
||||
# PARENTING
|
||||
if o.strategy == 'PARALLEL' or o.strategy == 'CROSS' or o.strategy == 'OUTLINEFILL':
|
||||
|
@ -664,7 +667,7 @@ async def sampleChunksNAxis(o, pathSamples, layers):
|
|||
|
||||
for l in layers:
|
||||
layerchunks.append([])
|
||||
layeractivechunks.append(camPathChunk([]))
|
||||
layeractivechunks.append(camPathChunkBuilder([]))
|
||||
lastrunchunks.append([])
|
||||
n = 0
|
||||
|
||||
|
@ -826,12 +829,18 @@ async def sampleChunksNAxis(o, pathSamples, layers):
|
|||
laststartpoint = startp
|
||||
lastendpoint = endp
|
||||
|
||||
# convert everything to actual chunks
|
||||
# rather than chunkBuilders
|
||||
for i, l in enumerate(layers):
|
||||
layeractivechunks[i]=layeractivechunks[i].to_chunk() if layeractivechunks[i] is not None else None
|
||||
|
||||
|
||||
for i, l in enumerate(layers):
|
||||
ch = layeractivechunks[i]
|
||||
if len(ch.points) > 0:
|
||||
layerchunks[i].append(ch)
|
||||
thisrunchunks[i].append(ch)
|
||||
layeractivechunks[i] = camPathChunk([])
|
||||
layeractivechunks[i] = None
|
||||
|
||||
if o.strategy == 'PARALLEL' or o.strategy == 'CROSS' or o.strategy == 'OUTLINEFILL':
|
||||
parentChildDist(thisrunchunks[i], lastrunchunks[i], o)
|
||||
|
@ -1021,7 +1030,7 @@ async def connectChunksLow(chunks, o):
|
|||
pos = (0, 0, 0)
|
||||
|
||||
for ch in chunks:
|
||||
if len(ch.points) > 0:
|
||||
if ch.count() > 0:
|
||||
if lastch is not None and (ch.distStart(pos, o) < mergedist):
|
||||
# CARVE should lift allways, when it goes below surface...
|
||||
# print(mergedist,ch.dist(pos,o))
|
||||
|
@ -1035,16 +1044,16 @@ async def connectChunksLow(chunks, o):
|
|||
if o.optimisation.use_opencamlib and o.optimisation.use_exact and (
|
||||
o.strategy == 'PARALLEL' or o.strategy == 'CROSS' or o.strategy == 'PENCIL'):
|
||||
chunks_to_resample.append(
|
||||
(connectedchunks[-1], len(connectedchunks[-1].points), len(between.points)))
|
||||
(connectedchunks[-1], connectedchunks[-1].count(), between.count()))
|
||||
|
||||
connectedchunks[-1].points.extend(between.points)
|
||||
connectedchunks[-1].points.extend(ch.points)
|
||||
connectedchunks[-1].extend(between.get_points_np())
|
||||
connectedchunks[-1].extend(ch.get_points_np())
|
||||
else:
|
||||
connectedchunks.append(ch)
|
||||
lastch = ch
|
||||
pos = lastch.points[-1]
|
||||
pos = lastch.get_point(-1)
|
||||
|
||||
if o.optimisation.use_opencamlib and o.optimisation.use_exact and o.strategy != 'CUTOUT' and o.strategy != 'POCKET':
|
||||
if o.optimisation.use_opencamlib and o.optimisation.use_exact and o.strategy != 'CUTOUT' and o.strategy != 'POCKET' and o.strategy != 'WATERLINE':
|
||||
await oclResampleChunks(o, chunks_to_resample,use_cached_mesh=True)
|
||||
|
||||
return connectedchunks
|
||||
|
@ -1069,7 +1078,7 @@ def getClosest(o, pos, chunks):
|
|||
return ch
|
||||
|
||||
|
||||
async def sortChunks(chunks, o):
|
||||
async def sortChunks(chunks, o,last_pos=None):
|
||||
if o.strategy != 'WATERLINE':
|
||||
await progress_async('sorting paths')
|
||||
sys.setrecursionlimit(100000) # the getNext() function of CamPathChunk was running out of recursion limits.
|
||||
|
@ -1080,7 +1089,7 @@ async def sortChunks(chunks, o):
|
|||
last_progress_time=time.time()
|
||||
total= len(chunks)
|
||||
i = len(chunks)
|
||||
pos = (0, 0, 0)
|
||||
pos = (0, 0, 0) if last_pos is None else last_pos
|
||||
while len(chunks) > 0:
|
||||
if o.strategy != 'WATERLINE' and time.time()-last_progress_time>0.1:
|
||||
await progress_async("Sorting paths",100.0*(total-len(chunks))/total)
|
||||
|
@ -1106,7 +1115,7 @@ async def sortChunks(chunks, o):
|
|||
chunks.remove(ch)
|
||||
sortedchunks.append(ch)
|
||||
lastch = ch
|
||||
pos = lastch.points[-1]
|
||||
pos = lastch.get_point(-1)
|
||||
# print(i, len(chunks))
|
||||
# experimental fix for infinite loop problem
|
||||
# else:
|
||||
|
|
Ładowanie…
Reference in New Issue