kopia lustrzana https://github.com/vilemduha/blendercam
Merge branch 'master' of https://github.com/vilemnovak/blendercam
commit
74f742bcd3
|
|
@ -1,6 +1,8 @@
|
|||
import bpy
|
||||
from cam import utils, simple,polygon_utils_cam
|
||||
import Polygon
|
||||
import shapely
|
||||
from shapely import geometry as sgeometry
|
||||
from shapely import affinity
|
||||
import random
|
||||
#this algorithm takes all selected curves,
|
||||
#converts them to polygons,
|
||||
|
|
@ -29,23 +31,21 @@ def packCurves():
|
|||
bpy.ops.object.rotation_clear()
|
||||
|
||||
chunks=utils.curveToChunks(ob)
|
||||
npolys=utils.chunksToPolys(chunks)
|
||||
npolys=utils.chunksToShapely(chunks)
|
||||
#add all polys in silh to one poly
|
||||
poly=Polygon.Polygon()
|
||||
for p in npolys:
|
||||
poly+=p
|
||||
poly.simplify()
|
||||
poly=polygon_utils_cam.outlinePoly(poly,distance/1.5,8,True,.003,offset = True)
|
||||
poly=shapely.ops.unary_union(npolys)
|
||||
|
||||
poly=poly.buffer(distance/1.5,8)
|
||||
polyfield.append([[0,0],0.0,poly,ob,z])
|
||||
random.shuffle(polyfield)
|
||||
#primitive layout here:
|
||||
allpoly=Polygon.Polygon()#main collision poly.
|
||||
allpoly=sgeometry.Polygon()#main collision poly.
|
||||
|
||||
|
||||
shift=0.0015#one milimeter by now.
|
||||
rotchange=.3123456#in radians
|
||||
|
||||
xmin,xmax,ymin,ymax=polyfield[0][2].boundingBox()
|
||||
xmin,xmax,ymin,ymax=polyfield[0][2].bounds()
|
||||
if direction=='X':
|
||||
mindist=-xmin
|
||||
else:
|
||||
|
|
@ -75,11 +75,11 @@ def packCurves():
|
|||
#print(x,y)
|
||||
#p=Polygon.Polygon(porig)
|
||||
p=porig
|
||||
p.rotate(rot,0,0)
|
||||
p.shift(x,y)
|
||||
ptrans=affinity.rotate(p,rot,origin=sgeometry.Point(0,0), use_radians = True)
|
||||
ptrans = affinity.translate(ptrans,x,y)
|
||||
|
||||
xmin,xmax,ymin,ymax=p.boundingBox()
|
||||
if xmin>0 and ymin>0 and ((direction=='Y' and xmax<sheetsizex) or (direction=='X' and ymax<sheetsizey)) and not p.overlaps(allpoly):
|
||||
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 ptrans.crosses(allpoly):
|
||||
#we do more good solutions, choose best out of them:
|
||||
hits+=1
|
||||
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
|
||||
placed=True
|
||||
|
|
@ -115,20 +113,21 @@ def packCurves():
|
|||
#print(iter)
|
||||
|
||||
#reset polygon to best position here:
|
||||
p.rotate(best[2],0,0)
|
||||
p.shift(best[0],best[1])
|
||||
ptrans=affinity.rotate(ptrans,best[2],origin=sgeometry.Point(0,0))
|
||||
ptrans = affinity.translate(ptrans,best[0],best[1])
|
||||
|
||||
#polygon_utils_cam.polyToMesh(p,0.1)#debug visualisation
|
||||
keep=[]
|
||||
|
||||
npoly=Polygon.Polygon()
|
||||
npoly=allpoly.union(ptrans)
|
||||
'''
|
||||
for ci in range(0,len(allpoly)):
|
||||
cminx,cmaxx,cminy,cmaxy=allpoly.boundingBox(ci)
|
||||
if direction=='X' and cmaxx>mindist-.1:
|
||||
npoly.addContour(allpoly[ci])
|
||||
if direction=='Y' and cmaxy>mindist-.1:
|
||||
npoly.addContour(allpoly[ci])
|
||||
|
||||
'''
|
||||
allpoly=npoly
|
||||
#polygon_utils_cam.polyToMesh(allpoly,0.1)#debug visualisation
|
||||
|
||||
|
|
|
|||
|
|
@ -1828,7 +1828,6 @@ def getAmbient(o):
|
|||
#for p in polys:
|
||||
# o.limit_poly+=p
|
||||
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.ambient = o.ambient.intersection(o.limit_poly)
|
||||
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))
|
||||
i+=1
|
||||
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)
|
||||
outlines.append(p1)
|
||||
|
||||
|
|
@ -1866,7 +1864,7 @@ def getObjectOutline(radius,o,Offset):#FIXME: make this one operation independen
|
|||
#print(p)
|
||||
outline=shapely.ops.unary_union(outlines)
|
||||
#outline = sgeometry.MultiPolygon([outline])
|
||||
shapelyToCurve('oboutline',outline,0)
|
||||
#shapelyToCurve('oboutline',outline,0)
|
||||
return outline
|
||||
|
||||
def addOrientationObject(o):
|
||||
|
|
@ -2331,17 +2329,18 @@ def strategy_cutout( o ):
|
|||
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)
|
||||
#p=outlinePoly(p,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offset)
|
||||
|
||||
|
||||
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)
|
||||
|
|
@ -2542,98 +2541,41 @@ def getPath3axis(context, operation):
|
|||
chunksFromCurve=[]
|
||||
lastchunks=[]
|
||||
centers=None
|
||||
firstoutline = p#for testing in the end.
|
||||
prest = p.buffer(-o.cutter_diameter/2, o.circle_detail)
|
||||
#shapelyToCurve('testik',p,0)
|
||||
while not p.is_empty:
|
||||
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)
|
||||
chunksFromCurve.extend(nchunks)
|
||||
parentChildDist(lastchunks,nchunks,o)
|
||||
|
||||
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)
|
||||
progress('outlining polygons ',percent)
|
||||
p=pnew
|
||||
|
|
@ -2748,7 +2690,6 @@ def getPath3axis(context, operation):
|
|||
#print('çoutline')
|
||||
#print(c)
|
||||
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('çoutline')
|
||||
#print(coutline)
|
||||
|
|
@ -2952,7 +2893,7 @@ def getPath3axis(context, operation):
|
|||
#polyToMesh('fillrest',restpoly,z)
|
||||
|
||||
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
|
||||
i=0
|
||||
while not restpoly.is_empty:
|
||||
|
|
@ -2969,7 +2910,7 @@ def getPath3axis(context, operation):
|
|||
lastchunks=nchunks
|
||||
#slicechunks.extend(polyToChunks(restpoly,z))
|
||||
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
|
||||
#print(i)
|
||||
i=0
|
||||
|
|
@ -2990,7 +2931,7 @@ def getPath3axis(context, operation):
|
|||
restpoly=boundrect.difference(lastslice)
|
||||
|
||||
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
|
||||
while not restpoly.is_empty: #'GeometryCollection':#len(restpoly.boundary.coords)>0:
|
||||
#print(i)
|
||||
|
|
@ -3002,7 +2943,6 @@ def getPath3axis(context, operation):
|
|||
lastchunks=nchunks
|
||||
#slicechunks.extend(polyToChunks(restpoly,z))
|
||||
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
|
||||
|
||||
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue