kopia lustrzana https://github.com/vilemduha/blendercam
Merge branch 'master' of https://github.com/vilemnovak/blendercam
commit
74f742bcd3
|
|
@ -1,6 +1,8 @@
|
||||||
import bpy
|
import bpy
|
||||||
from cam import utils, simple,polygon_utils_cam
|
from cam import utils, simple,polygon_utils_cam
|
||||||
import Polygon
|
import shapely
|
||||||
|
from shapely import geometry as sgeometry
|
||||||
|
from shapely import affinity
|
||||||
import random
|
import random
|
||||||
#this algorithm takes all selected curves,
|
#this algorithm takes all selected curves,
|
||||||
#converts them to polygons,
|
#converts them to polygons,
|
||||||
|
|
@ -29,23 +31,21 @@ def packCurves():
|
||||||
bpy.ops.object.rotation_clear()
|
bpy.ops.object.rotation_clear()
|
||||||
|
|
||||||
chunks=utils.curveToChunks(ob)
|
chunks=utils.curveToChunks(ob)
|
||||||
npolys=utils.chunksToPolys(chunks)
|
npolys=utils.chunksToShapely(chunks)
|
||||||
#add all polys in silh to one poly
|
#add all polys in silh to one poly
|
||||||
poly=Polygon.Polygon()
|
poly=shapely.ops.unary_union(npolys)
|
||||||
for p in npolys:
|
|
||||||
poly+=p
|
poly=poly.buffer(distance/1.5,8)
|
||||||
poly.simplify()
|
|
||||||
poly=polygon_utils_cam.outlinePoly(poly,distance/1.5,8,True,.003,offset = True)
|
|
||||||
polyfield.append([[0,0],0.0,poly,ob,z])
|
polyfield.append([[0,0],0.0,poly,ob,z])
|
||||||
random.shuffle(polyfield)
|
random.shuffle(polyfield)
|
||||||
#primitive layout here:
|
#primitive layout here:
|
||||||
allpoly=Polygon.Polygon()#main collision poly.
|
allpoly=sgeometry.Polygon()#main collision poly.
|
||||||
|
|
||||||
|
|
||||||
shift=0.0015#one milimeter by now.
|
shift=0.0015#one milimeter by now.
|
||||||
rotchange=.3123456#in radians
|
rotchange=.3123456#in radians
|
||||||
|
|
||||||
xmin,xmax,ymin,ymax=polyfield[0][2].boundingBox()
|
xmin,xmax,ymin,ymax=polyfield[0][2].bounds()
|
||||||
if direction=='X':
|
if direction=='X':
|
||||||
mindist=-xmin
|
mindist=-xmin
|
||||||
else:
|
else:
|
||||||
|
|
@ -75,11 +75,11 @@ def packCurves():
|
||||||
#print(x,y)
|
#print(x,y)
|
||||||
#p=Polygon.Polygon(porig)
|
#p=Polygon.Polygon(porig)
|
||||||
p=porig
|
p=porig
|
||||||
p.rotate(rot,0,0)
|
ptrans=affinity.rotate(p,rot,origin=sgeometry.Point(0,0), use_radians = True)
|
||||||
p.shift(x,y)
|
ptrans = affinity.translate(ptrans,x,y)
|
||||||
|
|
||||||
xmin,xmax,ymin,ymax=p.boundingBox()
|
xmin,xmax,ymin,ymax=p.bounds
|
||||||
if xmin>0 and ymin>0 and ((direction=='Y' and xmax<sheetsizex) or (direction=='X' and ymax<sheetsizey)) and not p.overlaps(allpoly):
|
if xmin>0 and ymin>0 and ((direction=='Y' and xmax<sheetsizex) or (direction=='X' and ymax<sheetsizey)) and not ptrans.crosses(allpoly):
|
||||||
#we do more good solutions, choose best out of them:
|
#we do more good solutions, choose best out of them:
|
||||||
hits+=1
|
hits+=1
|
||||||
if best==None:
|
if best==None:
|
||||||
|
|
@ -96,8 +96,6 @@ def packCurves():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
p.shift(-x,-y)
|
|
||||||
p.rotate(-rot,0,0)
|
|
||||||
|
|
||||||
if hits>=15 or (iter>10000 and hits>0):#here was originally more, but 90% of best solutions are still 1
|
if hits>=15 or (iter>10000 and hits>0):#here was originally more, but 90% of best solutions are still 1
|
||||||
placed=True
|
placed=True
|
||||||
|
|
@ -115,20 +113,21 @@ def packCurves():
|
||||||
#print(iter)
|
#print(iter)
|
||||||
|
|
||||||
#reset polygon to best position here:
|
#reset polygon to best position here:
|
||||||
p.rotate(best[2],0,0)
|
ptrans=affinity.rotate(ptrans,best[2],origin=sgeometry.Point(0,0))
|
||||||
p.shift(best[0],best[1])
|
ptrans = affinity.translate(ptrans,best[0],best[1])
|
||||||
|
|
||||||
#polygon_utils_cam.polyToMesh(p,0.1)#debug visualisation
|
#polygon_utils_cam.polyToMesh(p,0.1)#debug visualisation
|
||||||
keep=[]
|
keep=[]
|
||||||
|
|
||||||
npoly=Polygon.Polygon()
|
npoly=allpoly.union(ptrans)
|
||||||
|
'''
|
||||||
for ci in range(0,len(allpoly)):
|
for ci in range(0,len(allpoly)):
|
||||||
cminx,cmaxx,cminy,cmaxy=allpoly.boundingBox(ci)
|
cminx,cmaxx,cminy,cmaxy=allpoly.boundingBox(ci)
|
||||||
if direction=='X' and cmaxx>mindist-.1:
|
if direction=='X' and cmaxx>mindist-.1:
|
||||||
npoly.addContour(allpoly[ci])
|
npoly.addContour(allpoly[ci])
|
||||||
if direction=='Y' and cmaxy>mindist-.1:
|
if direction=='Y' and cmaxy>mindist-.1:
|
||||||
npoly.addContour(allpoly[ci])
|
npoly.addContour(allpoly[ci])
|
||||||
|
'''
|
||||||
allpoly=npoly
|
allpoly=npoly
|
||||||
#polygon_utils_cam.polyToMesh(allpoly,0.1)#debug visualisation
|
#polygon_utils_cam.polyToMesh(allpoly,0.1)#debug visualisation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1828,7 +1828,6 @@ def getAmbient(o):
|
||||||
#for p in polys:
|
#for p in polys:
|
||||||
# o.limit_poly+=p
|
# o.limit_poly+=p
|
||||||
if o.ambient_cutter_restrict:
|
if o.ambient_cutter_restrict:
|
||||||
#o.limit_poly = outlinePoly(o.limit_poly,o.cutter_diameter/2,o.circle_detail,o.optimize,o.optimize_threshold,offset = False)
|
|
||||||
o.limit_poly = o.limit_poly.buffer(o.cutter_diameter/2,resolution = o.circle_detail)
|
o.limit_poly = o.limit_poly.buffer(o.cutter_diameter/2,resolution = o.circle_detail)
|
||||||
o.ambient = o.ambient.intersection(o.limit_poly)
|
o.ambient = o.ambient.intersection(o.limit_poly)
|
||||||
o.update_ambient_tag=False
|
o.update_ambient_tag=False
|
||||||
|
|
@ -1853,7 +1852,6 @@ def getObjectOutline(radius,o,Offset):#FIXME: make this one operation independen
|
||||||
print(p1.type,len(polygons))
|
print(p1.type,len(polygons))
|
||||||
i+=1
|
i+=1
|
||||||
if radius>0:
|
if radius>0:
|
||||||
#p=outlinePoly(p,radius,o.circle_detail,o.optimize,o.optimize_threshold*0.000001,Offset)
|
|
||||||
p1 = p1.buffer(radius*offset,resolution = o.circle_detail)
|
p1 = p1.buffer(radius*offset,resolution = o.circle_detail)
|
||||||
outlines.append(p1)
|
outlines.append(p1)
|
||||||
|
|
||||||
|
|
@ -1866,7 +1864,7 @@ def getObjectOutline(radius,o,Offset):#FIXME: make this one operation independen
|
||||||
#print(p)
|
#print(p)
|
||||||
outline=shapely.ops.unary_union(outlines)
|
outline=shapely.ops.unary_union(outlines)
|
||||||
#outline = sgeometry.MultiPolygon([outline])
|
#outline = sgeometry.MultiPolygon([outline])
|
||||||
shapelyToCurve('oboutline',outline,0)
|
#shapelyToCurve('oboutline',outline,0)
|
||||||
return outline
|
return outline
|
||||||
|
|
||||||
def addOrientationObject(o):
|
def addOrientationObject(o):
|
||||||
|
|
@ -2331,17 +2329,18 @@ def strategy_cutout( o ):
|
||||||
offset=True
|
offset=True
|
||||||
if o.cut_type=='INSIDE':
|
if o.cut_type=='INSIDE':
|
||||||
offset=False
|
offset=False
|
||||||
|
|
||||||
p=getObjectOutline(o.cutter_diameter/2,o,offset)
|
p=getObjectOutline(o.cutter_diameter/2,o,offset)
|
||||||
if o.outlines_count>1:
|
if o.outlines_count>1:
|
||||||
for i in range(1,o.outlines_count):
|
for i in range(1,o.outlines_count):
|
||||||
chunksFromCurve.extend(shapelyToChunks(p,-1))
|
chunksFromCurve.extend(shapelyToChunks(p,-1))
|
||||||
p = p.buffer(distance = o.dist_between_paths * offset, resolution = o.circle_detail)
|
p = p.buffer(distance = o.dist_between_paths * offset, resolution = o.circle_detail)
|
||||||
#p=outlinePoly(p,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offset)
|
|
||||||
|
|
||||||
|
|
||||||
chunksFromCurve.extend(shapelyToChunks(p,-1))
|
chunksFromCurve.extend(shapelyToChunks(p,-1))
|
||||||
if o.outlines_count>1 and o.movement_insideout=='OUTSIDEIN':
|
if o.outlines_count>1 and o.movement_insideout=='OUTSIDEIN':
|
||||||
chunksFromCurve.reverse()
|
chunksFromCurve.reverse()
|
||||||
|
|
||||||
#parentChildPoly(chunksFromCurve,chunksFromCurve,o)
|
#parentChildPoly(chunksFromCurve,chunksFromCurve,o)
|
||||||
chunksFromCurve=limitChunks(chunksFromCurve,o)
|
chunksFromCurve=limitChunks(chunksFromCurve,o)
|
||||||
parentChildPoly(chunksFromCurve,chunksFromCurve,o)
|
parentChildPoly(chunksFromCurve,chunksFromCurve,o)
|
||||||
|
|
@ -2542,98 +2541,41 @@ def getPath3axis(context, operation):
|
||||||
chunksFromCurve=[]
|
chunksFromCurve=[]
|
||||||
lastchunks=[]
|
lastchunks=[]
|
||||||
centers=None
|
centers=None
|
||||||
|
firstoutline = p#for testing in the end.
|
||||||
|
prest = p.buffer(-o.cutter_diameter/2, o.circle_detail)
|
||||||
#shapelyToCurve('testik',p,0)
|
#shapelyToCurve('testik',p,0)
|
||||||
while not p.is_empty:
|
while not p.is_empty:
|
||||||
nchunks=shapelyToChunks(p,o.min.z)
|
nchunks=shapelyToChunks(p,o.min.z)
|
||||||
|
|
||||||
|
|
||||||
|
pnew=p.buffer(-o.dist_between_paths,o.circle_detail)
|
||||||
|
|
||||||
|
if o.dist_between_paths>o.cutter_diameter/2.0:
|
||||||
|
prest= prest.difference(pnew.boundary.buffer(o.cutter_diameter/2, o.circle_detail))
|
||||||
|
if not(pnew.contains(prest)):
|
||||||
|
#shapelyToCurve('cesta',pnew,0)
|
||||||
|
#shapelyToCurve('problemas',prest,0)
|
||||||
|
prest = shapelyToMultipolygon(prest)
|
||||||
|
fine=[]
|
||||||
|
go = []
|
||||||
|
for p1 in prest:
|
||||||
|
if pnew.contains(p1):
|
||||||
|
fine.append(p1)
|
||||||
|
else:
|
||||||
|
go.append(p1)
|
||||||
|
if len(go)>0:
|
||||||
|
for p1 in go:
|
||||||
|
nchunks1=shapelyToChunks(p1,o.min.z)
|
||||||
|
nchunks.extend(nchunks1)
|
||||||
|
prest=sgeometry.MultiPolygon(fine)
|
||||||
|
|
||||||
nchunks=limitChunks(nchunks,o)
|
nchunks=limitChunks(nchunks,o)
|
||||||
chunksFromCurve.extend(nchunks)
|
chunksFromCurve.extend(nchunks)
|
||||||
parentChildDist(lastchunks,nchunks,o)
|
parentChildDist(lastchunks,nchunks,o)
|
||||||
|
|
||||||
lastchunks=nchunks
|
lastchunks=nchunks
|
||||||
|
|
||||||
pnew=p.buffer(-o.dist_between_paths,o.circle_detail)
|
|
||||||
#pnew=outlinePoly(p,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,False)
|
|
||||||
|
|
||||||
if o.dist_between_paths>o.cutter_diameter/2.0:#this mess under this IF condition is here ONLY because of the ability to have stepover> than cutter radius. Other CAM softwares don't allow this at all, maybe because of this mathematical problem and performance cost, but into soft materials, this is good to have.
|
|
||||||
o.warnings=o.warnings+'Distance between paths larger\n than cutter radius can result in uncut areas!\n '
|
|
||||||
|
|
||||||
contours_before=len(p.boundary)
|
|
||||||
|
|
||||||
|
|
||||||
if centers==None:
|
|
||||||
centers=[]
|
|
||||||
print(p.type)
|
|
||||||
p = shapelyToMultipolygon(p)
|
|
||||||
for i in range(0,len(p)):
|
|
||||||
centers.append(p[i].centroid)
|
|
||||||
|
|
||||||
pnew = shapelyToMultipolygon(pnew)
|
|
||||||
contours_after=len(pnew)
|
|
||||||
newcenters=[]
|
|
||||||
|
|
||||||
do_test=False
|
|
||||||
for ci in range(0,len(pnew)):
|
|
||||||
newcenters.append(pnew.centroid)
|
|
||||||
#dodelat
|
|
||||||
if len(p)>ci:#comparing polygons to detect larger changes in shape
|
|
||||||
#print(ci,len(p))
|
|
||||||
bb1=p[ci].bounds
|
|
||||||
bb2=pnew[ci].bounds
|
|
||||||
d1=dist2d((newcenters[ci].x,newcenters[ci].y),(centers[ci].x,centers[ci].y))
|
|
||||||
d2=0
|
|
||||||
for bbi in range(0,4):
|
|
||||||
d2=max(d2,abs(bb2[bbi]-bb1[bbi]))
|
|
||||||
|
|
||||||
if contours_after!=contours_before or d1>o.dist_between_paths or d2>o.dist_between_paths*2:
|
|
||||||
do_test=True
|
|
||||||
#print(contours_before,contours_after)
|
|
||||||
|
|
||||||
if len(pnew)==0:
|
|
||||||
do_test=True
|
|
||||||
#print(contours_before,contours_after)
|
|
||||||
|
|
||||||
if do_test:
|
|
||||||
print('testing')
|
|
||||||
prest=p.buffer(-o.cutter_diameter/2.0,o.circle_detail)#this estimates if there was a rest on the last cut
|
|
||||||
#prest=outlinePoly(p,o.cutter_diameter/2.0,o.circle_detail,o.optimize,o.optimize_threshold,False)#this estimates if there was a rest on the last cut
|
|
||||||
|
|
||||||
prest = shapelyToMultipolygon(prest)
|
|
||||||
|
|
||||||
for ci,p in enumerate(prest):#.geom?
|
|
||||||
bbcontour=p.bounds
|
|
||||||
add=False
|
|
||||||
#if len(pnew)>ci:
|
|
||||||
|
|
||||||
d=0
|
|
||||||
bb2=pnew.bounds
|
|
||||||
bb1=prest.bounds
|
|
||||||
|
|
||||||
if bb2!=():
|
|
||||||
for bbi in range(0,4):
|
|
||||||
print(bb1,bb2)
|
|
||||||
|
|
||||||
d=max(d,abs(bb2[bbi]-bb1[bbi]))
|
|
||||||
#test to estimate if some of the paths might have disappeared:
|
|
||||||
if d>o.dist_between_paths*2:
|
|
||||||
add=True
|
|
||||||
#print('pnew boundbox vs restboundbox')
|
|
||||||
#print(d/o.dist_between_paths)
|
|
||||||
|
|
||||||
if min(bbcontour[1]-bbcontour[0],bbcontour[3]-bbcontour[2])<o.dist_between_paths*2:
|
|
||||||
add=True
|
|
||||||
#print('small rest boundbox')
|
|
||||||
|
|
||||||
if add:
|
|
||||||
#print('adding extra contour rest')
|
|
||||||
#print(prest[ci])
|
|
||||||
rest=spolygon.Polygon(prest[ci])
|
|
||||||
nchunks=shapelyToChunks(rest,o.min.z)
|
|
||||||
nchunks=limitChunks(nchunks,o)
|
|
||||||
parentChildDist(lastchunks,nchunks,o)
|
|
||||||
nchunks.extend(chunksFromCurve)#appending these to the beginning, so they get milled first.
|
|
||||||
chunksFromCurve=nchunks
|
|
||||||
|
|
||||||
centers=newcenters
|
|
||||||
|
|
||||||
percent=int(i/approxn*100)
|
percent=int(i/approxn*100)
|
||||||
progress('outlining polygons ',percent)
|
progress('outlining polygons ',percent)
|
||||||
p=pnew
|
p=pnew
|
||||||
|
|
@ -2748,7 +2690,6 @@ def getPath3axis(context, operation):
|
||||||
#print('çoutline')
|
#print('çoutline')
|
||||||
#print(c)
|
#print(c)
|
||||||
coutline = c.buffer(o.cutter_diameter/2,o.circle_detail)
|
coutline = c.buffer(o.cutter_diameter/2,o.circle_detail)
|
||||||
#coutline = outlinePoly(c,o.cutter_diameter/2,o.circle_detail,o.optimize,o.optimize_threshold,offset = True)
|
|
||||||
#print(h)
|
#print(h)
|
||||||
#print('çoutline')
|
#print('çoutline')
|
||||||
#print(coutline)
|
#print(coutline)
|
||||||
|
|
@ -2952,7 +2893,7 @@ def getPath3axis(context, operation):
|
||||||
#polyToMesh('fillrest',restpoly,z)
|
#polyToMesh('fillrest',restpoly,z)
|
||||||
|
|
||||||
restpoly=restpoly.buffer(-o.dist_between_paths, resolution = o.circle_detail)
|
restpoly=restpoly.buffer(-o.dist_between_paths, resolution = o.circle_detail)
|
||||||
#outlinePoly(restpoly,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offs)
|
|
||||||
fillz = z
|
fillz = z
|
||||||
i=0
|
i=0
|
||||||
while not restpoly.is_empty:
|
while not restpoly.is_empty:
|
||||||
|
|
@ -2969,7 +2910,7 @@ def getPath3axis(context, operation):
|
||||||
lastchunks=nchunks
|
lastchunks=nchunks
|
||||||
#slicechunks.extend(polyToChunks(restpoly,z))
|
#slicechunks.extend(polyToChunks(restpoly,z))
|
||||||
restpoly=restpoly.buffer(-o.dist_between_paths, resolution = o.circle_detail)
|
restpoly=restpoly.buffer(-o.dist_between_paths, resolution = o.circle_detail)
|
||||||
#restpoly=outlinePoly(restpoly,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offs)
|
|
||||||
i+=1
|
i+=1
|
||||||
#print(i)
|
#print(i)
|
||||||
i=0
|
i=0
|
||||||
|
|
@ -2990,7 +2931,7 @@ def getPath3axis(context, operation):
|
||||||
restpoly=boundrect.difference(lastslice)
|
restpoly=boundrect.difference(lastslice)
|
||||||
|
|
||||||
restpoly=restpoly.buffer(-o.dist_between_paths, resolution = o.circle_detail)
|
restpoly=restpoly.buffer(-o.dist_between_paths, resolution = o.circle_detail)
|
||||||
#restpoly=outlinePoly(restpoly,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offs)
|
|
||||||
i=0
|
i=0
|
||||||
while not restpoly.is_empty: #'GeometryCollection':#len(restpoly.boundary.coords)>0:
|
while not restpoly.is_empty: #'GeometryCollection':#len(restpoly.boundary.coords)>0:
|
||||||
#print(i)
|
#print(i)
|
||||||
|
|
@ -3002,7 +2943,6 @@ def getPath3axis(context, operation):
|
||||||
lastchunks=nchunks
|
lastchunks=nchunks
|
||||||
#slicechunks.extend(polyToChunks(restpoly,z))
|
#slicechunks.extend(polyToChunks(restpoly,z))
|
||||||
restpoly=restpoly.buffer(-o.dist_between_paths, resolution = o.circle_detail)
|
restpoly=restpoly.buffer(-o.dist_between_paths, resolution = o.circle_detail)
|
||||||
#restpoly=outlinePoly(restpoly,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offs)
|
|
||||||
i+=1
|
i+=1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue