diff --git a/scripts/addons/cam/chunk.py b/scripts/addons/cam/chunk.py index 7a50dbcb..cd7fbd00 100644 --- a/scripts/addons/cam/chunk.py +++ b/scripts/addons/cam/chunk.py @@ -3,8 +3,8 @@ import Polygon import shapely from shapely.geometry import polygon as spolygon from shapely import ops -from shapely import geometry - +from shapely import geometry as sgeometry +from cam import polygon_utils_cam from cam import simple from cam.simple import * @@ -130,7 +130,7 @@ class camPathChunk: #self.unsortedchildren=False # return self - def getNextClosest(self,o,pos):#this should be deprecated after reworking sortchunks a bit + def getNextClosest(self,o,pos): mind=100000000000 self.cango=False @@ -155,10 +155,10 @@ class camPathChunk: ch=chtest mind=d if ch!=None: - print('found some') + #print('found some') return ch #self.unsortedchildren=False - print('returning none') + #print('returning none') return None @@ -540,7 +540,7 @@ def limitChunks(chunks,o, force=False):#TODO: this should at least add point on nch1=nch closed=True for s in ch.points: - sampled=o.ambient.isInside(s[0],s[1]) + sampled=o.ambient.contains(sgeometry.Point(s[0],s[1])) if not sampled and len(nch.points)>0: nch.closed=False closed=False @@ -569,8 +569,8 @@ def parentChildPoly(parents,children,o): #print(parent.poly) for child in children: #print(child.poly) - if child!=parent and len(child.poly)>0: - if parent.poly.isInside(child.poly[0][0][0],child.poly[0][0][1]): + if child!=parent:# and len(child.poly)>0 + if parent.poly.contains(sgeometry.Point(child.poly.boundary.coords[0])): parent.children.append(child) child.parents.append(parent) @@ -610,7 +610,7 @@ def parentChild(parents, children, o): if parent!=child: parent.children.append(child) child.parents.append(parent) - +''' def chunksToShapely(chunks):#this does more cleve chunks to Poly with hierarchies... ;) #print ('analyzing paths') #verts=[] @@ -631,6 +631,73 @@ def chunksToShapely(chunks):#this does more cleve chunks to Poly with hierarchie returnpolys.append(ch.poly) #print(len(returnpolys)) return returnpolys +''' + +def chunksToShapely(chunks):#this does more cleve chunks to Poly with hierarchies... ;) + #print ('analyzing paths') + #verts=[] + #pverts=[] + polys=[] + for ch in chunks:#first convert chunk to poly + if len(ch.points)>2: + pchunk=[] + ch.poly=sgeometry.Polygon(ch.points) + + for ppart in chunks:#then add hierarchy relations + for ptest in chunks: + + #if ppart!=ptest and len(ptest.poly)>0 and len(ppart.poly)>0 and ptest.poly.nPoints(0)>0 and ppart.poly.nPoints(0)>0: + if ppart!=ptest : + if ptest.poly.contains(ppart.poly): + #hierarchy works like this: - children get milled first. + #ptest.children.append(ppart) + ppart.parents.append(ptest) + + + for ch in chunks:#now make only simple polygons with holes, not more polys inside others + #print(len(chunks[polyi].parents)) + found=False + if len(ch.parents)%2==1: + + for parent in ch.parents: + if len(parent.parents)+1==len(ch.parents): + ch.nparents=[parent]#nparents serves as temporary storage for parents, not to get mixed with the first parenting during the check + found=True + break + + if not found: + ch.nparents=[] + + for ch in chunks:#then subtract the 1st level holes + ch.parents=ch.nparents + ch.nparents=None + if len(ch.parents)>0: + #print(len(ch.parents)) + #ch.parents[0].poly=ch.parents[0].poly-ch.poly + #print(ch.parents[0].poly,[ch.poly]) + print('addparent') + #polygon_utils_cam.shapelyToCurve('crust',ch.parents[0].poly,0) + #polygon_utils_cam.shapelyToCurve('hole',ch.poly,0) + ch.parents[0].poly = ch.parents[0].poly.difference(ch.poly)#sgeometry.Polygon( ch.parents[0].poly, ch.poly) + + + returnpolys=[] + + for polyi in range(0,len(chunks)):#export only the booleaned polygons + ch=chunks[polyi] + if len(ch.parents)==0: + #ch.poly.simplify()#TODO:THIS CHECK + returnpolys.append(ch.poly) + #if len(ch.poly.interiors)>0: + # print(ch.poly.interiors[0].coords[0]) + #polygon_utils_cam.shapelyToCurve('test',ch.poly,0) + #print(ch.poly.boundary) + print('shapely hierarchies') + #print(len(returnpolys)) + + + return returnpolys + def chunksToPolys(chunks):#this does more cleve chunks to Poly with hierarchies... ;) #print ('analyzing paths') @@ -734,6 +801,7 @@ def meshFromCurveToChunk(object): chunk.points.append((mesh.vertices[lastvi].co.x+x,mesh.vertices[lastvi].co.y+y,mesh.vertices[lastvi].co.z+z)) #else: # print('itisnot') + chunks.append(chunk) return chunks @@ -816,6 +884,32 @@ def polyToChunks(p,zlevel):# # return chunks +def shapelyToChunks(p,zlevel):# + chunks=[] + #p=sortContours(p) + seq=polygon_utils_cam.shapelyToCoords(p) + i=0 + for s in seq: + #progress(p[i]) + if len(s)>2: + chunk=camPathChunk([]) + chunk.poly=spolygon.Polygon(s)#this should maybe be LineString? but for sorting, we need polygon inside functions. + for v in s: + #progress (v) + + if len(v)>2: + chunk.points.append((v[0],v[1],v[2])) + else: + chunk.points.append((v[0],v[1],zlevel)) + + chunk.points.append((chunk.points[0][0],chunk.points[0][1],chunk.points[0][2]))#last point =first point + chunk.closed=True + chunks.append(chunk) + i+=1 + chunks.reverse()#this is for smaller shapes first. + # + return chunks + def chunkToPoly(chunk): pverts=[] @@ -826,6 +920,16 @@ def chunkToPoly(chunk): p=Polygon.Polygon(pverts) return p +def chunkToShapely(chunk): + #pverts=[] + + #for v in chunk.points: + + # pverts.append((v[0],v[1])) + + p=spolygon.Polygon(chunk.points) + return p + def chunksRefine(chunks,o): '''add extra points in between for chunks''' for ch in chunks: diff --git a/scripts/addons/cam/image_utils.py b/scripts/addons/cam/image_utils.py index ad5b3bfe..32e9c837 100644 --- a/scripts/addons/cam/image_utils.py +++ b/scripts/addons/cam/image_utils.py @@ -1446,9 +1446,9 @@ def imageToChunks(o,image, with_border=False): else: return [] -def imageToPoly(o,i, with_border=False): +def imageToShapely(o,i, with_border=False): polychunks=imageToChunks(o,i, with_border) - polys=chunksToPolys(polychunks) + polys=chunksToShapely(polychunks) #polys=orderPoly(polys) t=time.time() diff --git a/scripts/addons/cam/ops.py b/scripts/addons/cam/ops.py index 078906f7..9709ee1b 100644 --- a/scripts/addons/cam/ops.py +++ b/scripts/addons/cam/ops.py @@ -789,13 +789,13 @@ class CamObjectSilhouete(bpy.types.Operator): def execute(self, context):#this is almost same as getobjectoutline, just without the need of operation data ob=bpy.context.active_object self.silh=utils.getObjectSilhouete('OBJECTS', objects=bpy.context.selected_objects) - poly=Polygon.Polygon() - for p in self.silh: - for ci in range(0,len(p)): - poly.addContour(p[ci]) + #poly=Polygon.Polygon() + #for p in self.silh: + # for ci in range(0,len(p)): + # poly.addContour(p[ci]) bpy.context.scene.cursor_location=(0,0,0) - polygon_utils_cam.polyToMesh(ob.name+'_silhouette',poly,0)# - bpy.ops.object.convert(target='CURVE') + polygon_utils_cam.shapelyToCurve(ob.name+'_silhouette',self.silh,0)# + #bpy.ops.object.convert(target='CURVE') bpy.context.scene.cursor_location=ob.location bpy.ops.object.origin_set(type='ORIGIN_CURSOR') return {'FINISHED'} diff --git a/scripts/addons/cam/pattern.py b/scripts/addons/cam/pattern.py index e4be0d91..073c537b 100644 --- a/scripts/addons/cam/pattern.py +++ b/scripts/addons/cam/pattern.py @@ -8,6 +8,8 @@ from cam.simple import * from cam.chunk import * from cam import polygon_utils_cam from cam.polygon_utils_cam import * +import shapely +from shapely import geometry as sgeometry def getPathPatternParallel(o,angle): #minx,miny,minz,maxx,maxy,maxz=o.min.x,o.min.y,o.min.z,o.max.x,o.max.y,o.max.z @@ -324,8 +326,9 @@ def getPathPattern(operation): pathchunks=[] chunks=[] for p in polys: - p=outlinePoly(p,o.dist_between_paths/3,o.circle_detail,o.optimize,o.optimize_threshold,False)#first, move a bit inside, because otherwise the border samples go crazy very often changin between hit/non hit and making too many jumps in the path. - chunks.extend(polyToChunks(p,0)) + #p=outlinePoly(p,o.dist_between_paths/3,o.circle_detail,o.optimize,o.optimize_threshold,False)#first, move a bit inside, because otherwise the border samples go crazy very often changin between hit/non hit and making too many jumps in the path. + p=p.buffer(-o.dist_between_paths/3,o.circle_detail)#first, move a bit inside, because otherwise the border samples go crazy very often changin between hit/non hit and making too many jumps in the path. + chunks.extend(shapelyToChunks(p,0)) pathchunks.extend(chunks) lastchunks=chunks @@ -340,10 +343,11 @@ def getPathPattern(operation): for porig in polys: p=porig - while p.nPoints()>0: - p=outlinePoly(p,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,False) - if p.nPoints()>0: - nchunks=polyToChunks(p,zlevel) + while not p.is_empty:#:p.nPoints()>0: + #p=outlinePoly(p,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,False) + p=p.buffer(-o.dist_between_paths,o.circle_detail) + if not p.is_empty: + nchunks=shapelyToChunks(p,zlevel) #parentChildPoly(lastchunks,nchunks,o) pathchunks.extend(nchunks) lastchunks=nchunks @@ -362,9 +366,10 @@ def getPathPattern(operation): dist+=o.pixsize*0.85# this is here only because silhouette is still done with zbuffer method, even if we use bullet collisions. else: dist+=o.pixsize*2.5 - p=outlinePoly(p,dist,o.circle_detail,o.optimize,o.optimize_threshold,True) - if p.nPoints()>0: - chunks=polyToChunks(p,zlevel) + p=p.buffer(dist,o.circle_detail) + #p=outlinePoly(p,dist,o.circle_detail,o.optimize,o.optimize_threshold,True) + if not p.is_empty: + chunks=shapelyToChunks(p,zlevel) pathchunks.extend(chunks) lastchunks=chunks diff --git a/scripts/addons/cam/polygon_utils_cam.py b/scripts/addons/cam/polygon_utils_cam.py index 080bab55..3eab42d0 100644 --- a/scripts/addons/cam/polygon_utils_cam.py +++ b/scripts/addons/cam/polygon_utils_cam.py @@ -9,7 +9,7 @@ import Polygon import shapely from shapely.geometry import polygon as spolygon from shapely import ops -from shapely import geometry +from shapely import geometry as sgeometry SHAPELY=True #except: # SHAPELY=False @@ -17,7 +17,7 @@ SHAPELY=True def Polygon2Shapely(p): conts=[] - sp=geometry.Polygon() + sp=sgeometry.Polygon() holes=[] contours=[] #print(len(p)) @@ -39,7 +39,7 @@ def Polygon2Shapely(p): for h in holes: sp=sp.difference(h) - #sp=geometry.asMultiPolygon(conts) + #sp=sgeometry.asMultiPolygon(conts) #sp=ops.cascaded_union(sp) return sp @@ -69,7 +69,7 @@ def Circle(r,np): c.append((v.x,v.y)) v.rotate(e) - p=Polygon.Polygon(c) + p=spolygon.Polygon(c) return p def nRect(l,r): @@ -264,6 +264,53 @@ def polyToMesh(name,p,z): return bpy.context.active_object +def shapelyToCoords(anydata): + p=anydata + seq=[] + #print(p.type) + #print(p.geom_type) + if p.is_empty: + return seq + elif p.type=='Polygon': + + #print('polygon') + clen=len(p.exterior.coords) + #seq = sgeometry.asMultiLineString(p) + seq=[p.exterior.coords] + #print(len(p.interiors)) + for interior in p.interiors: + seq.append(interior.coords) + elif p.type=='MultiPolygon': + clen=0 + seq=[] + for sp in p: + clen+=len(sp.exterior.coords) + seq.append(sp.exterior.coords) + for interior in sp.interiors: + seq.append(interior.coords) + + elif p.type=='MultiLineString': + seq=[] + for linestring in p: + seq.append(linestring.coords) + elif p.type=='MultiPoint': + return; + elif p.type=='GeometryCollection': + #print(dir(p)) + #print(p.geometryType, p.geom_type) + clen=0 + seq=[] + #print(p.boundary.coordsd) + for sp in p: + clen+=len(sp.exterior.coords) + seq.append(sp.exterior.coords) + for interior in sp.interiors: + seq.extend(interior.coords) + #for g in p.geom: + # print(g.type) + + return seq + def shapelyToCurve(name,p,z): import bpy,bmesh from bpy_extras import object_utils @@ -274,24 +321,7 @@ def shapelyToCurve(name,p,z): #for c in p.exterior.coords: print(p.type) - if p.type=='Polygon': - clen=len(p.exterior.coords) - seq=[p.exterior.coords] - if p.type=='MultiPolygon': - clen=0 - seq=[] - for sp in p: - clen+=len(sp.exterior.coords) - seq.append(sp.exterior.coords) - - - elif p.type=='MultiLineString': - seq=[] - for linestring in p: - seq.append(linestring.coords) - elif p.type=='MultiPoint': - return; - + seq = shapelyToCoords(p) w = 1 # weight @@ -312,7 +342,7 @@ def shapelyToCurve(name,p,z): return objectdata#bpy.context.active_object - +'''#outdated? def orderPoly(polys): #sor poly, do holes e.t.c. p=Polygon.Polygon() levels=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]] @@ -345,4 +375,5 @@ def orderPoly(polys): #sor poly, do holes e.t.c. p.simplify() li+=1 - return p \ No newline at end of file + return p +''' \ No newline at end of file diff --git a/scripts/addons/cam/utils.py b/scripts/addons/cam/utils.py index a6acfc73..fe87eb67 100644 --- a/scripts/addons/cam/utils.py +++ b/scripts/addons/cam/utils.py @@ -55,14 +55,13 @@ from cam.image_utils import * from . import nc from cam.opencamlib.opencamlib import oclSample, oclSamplePoints, oclResampleChunks, oclGetWaterline -try: - from shapely.geometry import polygon as spolygon - from shapely import ops as sops - from shapely import geometry as sgeometry - #from shapely.geometry import * not possible until Polygon libs gets out finally.. - SHAPELY=True -except: - SHAPELY=False + +from shapely.geometry import polygon as spolygon +from shapely import ops as sops +from shapely import geometry as sgeometry +from shapely import affinity +#from shapely.geometry import * not possible until Polygon libs gets out finally.. +SHAPELY=True def positionObject(operation): ob=bpy.data.objects[operation.object_name] @@ -394,7 +393,7 @@ def sampleChunks(o,pathSamples,layers): n+=1 x=s[0] y=s[1] - if not o.ambient.isInside(x,y): + if not o.ambient.contains(sgeometry.Point(x,y)): newsample=(x,y,1) else: if o.use_opencamlib and o.use_exact: @@ -1335,16 +1334,23 @@ def silhoueteOffset(context,offset): bpy.context.scene.cursor_location=(0,0,0) ob=bpy.context.active_object if ob.type=='CURVE': - plist=curveToPolys(ob) + silhs=curveToShapely(ob) else: - plist=getObjectSilhouete('OBJECTS',[ob]) - p=Polygon.Polygon() - for p1 in plist: - p+=p1 - p=outlinePoly(p,abs(offset),64,True,abs(offset)*0.002,offset>0) + silhs=getObjectSilhouete('OBJECTS',[ob]) + #for p1 in plist: + # p+=p1 + print(silhs) + polys = [] + mp = sgeometry.MultiPolygon([silhs[0]],silhs[1:]) + for p in silhs: + polys.append(p.buffer(offset, resolution = 64)) + #mp = mp.buffer(offset,resolution = 64) + #p=outlinePoly(p,abs(offset),64,True,abs(offset)*0.002,offset>0) #print(p[0]) #p.shift(ob.location.x,ob.location.y) - polyToMesh('offset curve',p,ob.location.z) + #for p in polys: + for s in polys: + shapelyToCurve('offset curve',s,ob.location.z) return {'FINISHED'} @@ -1674,7 +1680,7 @@ def getOperationSilhouete(operation): i = samples > numpy.min(operation.zbuffer_image)#this fixes another numeric imprecision. chunks= imageToChunks(operation,i) - operation.silhouete=chunksToPolys(chunks) + operation.silhouete=chunksToShapely(chunks) #print(operation.silhouete) #this conversion happens because we need the silh to be oriented, for milling directions. else: @@ -1691,7 +1697,7 @@ def getObjectSilhouete(stype, objects=None): for ob in objects: chunks=curveToChunks(ob) allchunks.extend(chunks) - silhouete=chunksToPolys(allchunks) + silhouete=chunksToShapely(allchunks) elif stype=='OBJECTS': totfaces=0 @@ -1741,7 +1747,7 @@ def getObjectSilhouete(stype, objects=None): print(time.time()-t) t=time.time() - silhouete = [polygon_utils_cam.Shapely2Polygon(p)] + silhouete = [p]#[polygon_utils_cam.Shapely2Polygon(p)] ''' e=0.00001#one hunderth of a millimeter, should be ok. origtol=Polygon.getTolerance() @@ -1793,41 +1799,58 @@ def getAmbient(o): r=o.ambient_radius - m o.ambient = getObjectOutline( r , o , True)# in this method we need ambient from silhouete else: - o.ambient=Polygon.Polygon(((o.min.x + m ,o.min.y + m ) , (o.min.x + m ,o.max.y - m ),(o.max.x - m ,o.max.y - m ),(o.max.x - m , o.min.y + m ))) + #o.ambient=Polygon.Polygon(((o.min.x + m ,o.min.y + m ) , (o.min.x + m ,o.max.y - m ),(o.max.x - m ,o.max.y - m ),(o.max.x - m , o.min.y + m ))) + #SHAPELY stuff! + o.ambient=spolygon.Polygon(((o.min.x + m ,o.min.y + m ) , (o.min.x + m ,o.max.y - m ),(o.max.x - m ,o.max.y - m ),(o.max.x - m , o.min.y + m ))) if o.use_limit_curve: if o.limit_curve!='': limit_curve=bpy.data.objects[o.limit_curve] - polys=curveToPolys(limit_curve) - o.limit_poly=Polygon.Polygon() - for p in polys: - o.limit_poly+=p + #polys=curveToPolys(limit_curve) + polys = curveToShapely(limit_curve) + o.limit_poly=shapely.ops.unary_union(polys) + #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.ambient = o.ambient & o.limit_poly + #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 def getObjectOutline(radius,o,Offset):#FIXME: make this one operation independent #circle detail, optimize, optimize thresold. polygons=getOperationSilhouete(o) - outline=Polygon.Polygon() + i=0 #print('offseting polygons') + if Offset: + offset=1 + else: + offset=-1 + outlines=[] - for p in polygons:#sort by size before this??? - - + i=0 + #print(polygons, polygons.type) + for p1 in polygons:#sort by size before this??? + 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) - - if o.dont_merge: - for ci in range(0,len(p)): - outline.addContour(p[ci],p.isHole(ci)) - else: - #print(p) - outline=outline+p + #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) + + print(outlines) + if o.dont_merge: + outline=sgeometry.MultiPolygon(outlines) + #for ci in range(0,len(p)): + # outline.addContour(p[ci],p.isHole(ci)) + else: + #print(p) + outline=shapely.ops.unary_union(outlines) + #outline = sgeometry.MultiPolygon([outline]) + shapelyToCurve('oboutline',outline,0) return outline def addOrientationObject(o): @@ -2039,6 +2062,7 @@ def addAutoBridges(o): if ob.type=='CURVE': sply = curveToShapely(ob) + mw=ob.matrix_world for c in ob.data.splines: blength = o.cutter_diameter*1 @@ -2289,7 +2313,7 @@ def getPath3axis(context,operation): #print(ch.points) if len(ch.points)>2: - ch.poly=chunkToPoly(ch) + ch.poly=chunkToShapely(ch) #p.addContour(ch.poly) else: chunksFromCurve=[] @@ -2300,14 +2324,16 @@ def getPath3axis(context,operation): 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(polyToChunks(p,-1)) - p=outlinePoly(p,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offset) + 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(polyToChunks(p,-1)) + chunksFromCurve.extend(shapelyToChunks(p,-1)) if o.outlines_count>1 and o.movement_insideout=='OUTSIDEIN': chunksFromCurve.reverse() #parentChildPoly(chunksFromCurve,chunksFromCurve,o) @@ -2492,41 +2518,43 @@ def getPath3axis(context,operation): if o.strategy=='POCKET': p=getObjectOutline(o.cutter_diameter/2,o,False) - all=Polygon.Polygon(p) + #all=Polygon.Polygon(p) approxn=(min(o.max.x-o.min.x,o.max.y-o.min.y)/o.dist_between_paths)/2 i=0 chunks=[] chunksFromCurve=[] lastchunks=[] centers=None - while len(p)>0: - nchunks=polyToChunks(p,o.min.z) + #shapelyToCurve('testik',p,0) + while not p.is_empty: + nchunks=shapelyToChunks(p,o.min.z) nchunks=limitChunks(nchunks,o) chunksFromCurve.extend(nchunks) parentChildDist(lastchunks,nchunks,o) lastchunks=nchunks - pnew=outlinePoly(p,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,False) + 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) + contours_before=len(p.boundary) if centers==None: centers=[] - for ci in range(0,len(p)): - centers.append(p.center(ci)) - contours_after=len(pnew) + for p in range(0,len(p)): + centers.append(p.centroid()) + contours_after=len(pnew.boundary) newcenters=[] do_test=False for ci in range(0,len(pnew)): - newcenters.append(pnew.center(ci)) - + newcenters.append(pnew.centroid()) + dodelat if len(p)>ci:#comparing polygons to detect larger changes in shape #print(ci,len(p)) - bb1=p.boundingBox(ci) + bb1=p.bounds(ci) bb2=pnew.boundingBox(ci) d1=dist2d(newcenters[ci],centers[ci]) d2=0 @@ -2619,10 +2647,10 @@ def getPath3axis(context,operation): p=ch.points[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+o.cutter_diameter/2,o.circle_detail) - checkc.shift(p[0],p[1]) + checkc = affinity.translate(checkc,p[0],p[1]) covers=False for poly in o.silhouete: - if poly.covers(checkc): + if poly.contains(checkc): covers=True break; @@ -2683,10 +2711,11 @@ def getPath3axis(context,operation): rothelix.append(p) c.append((p[0],p[1])) - c=Polygon.Polygon(c) + c=sgeometry.Polygon(c) #print('çoutline') #print(c) - coutline = outlinePoly(c,o.cutter_diameter/2,o.circle_detail,o.optimize,o.optimize_threshold,offset = True) + 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) @@ -2695,7 +2724,7 @@ def getPath3axis(context,operation): covers=False for poly in o.silhouete: - if poly.covers(coutline): + if poly.contains(coutline): covers=True break; @@ -2817,7 +2846,7 @@ def getPath3axis(context,operation): ####################### nslices=ceil(abs(o.minz/o.slice_detail)) lastislice=numpy.array([]) - lastslice=Polygon.Polygon()#polyversion + lastslice=spolygon.Polygon()#polyversion layerstepinc=0 slicesfilled=0 @@ -2832,10 +2861,10 @@ def getPath3axis(context,operation): #print(z) #sliceimage=o.offset_image>z islice=o.offset_image>z - slicepolys=imageToPoly(o,islice,with_border=True) + slicepolys=imageToShapely(o,islice,with_border=True) #for pviz in slicepolys: # polyToMesh('slice',pviz,z) - poly=Polygon.Polygon()#polygversion + poly=spolygon.Polygon()#polygversion lastchunks=[] #imagechunks=imageToChunks(o,islice) #for ch in imagechunks: @@ -2847,10 +2876,10 @@ def getPath3axis(context,operation): #print('found polys',layerstepinc,len(slicepolys)) for p in slicepolys: #print('polypoints',p.nPoints(0)) - poly+=p#polygversion TODO: why is this added? + poly=poly.union(p)#polygversion TODO: why is this added? #print() #polyToMesh(p,z) - nchunks=polyToChunks(p,z) + nchunks=shapelyToChunks(p,z) nchunks=limitChunks(nchunks,o, force=True) #print('chunksnum',len(nchunks)) #if len(nchunks)>0: @@ -2874,25 +2903,27 @@ def getPath3axis(context,operation): layers=[[layerstart,layerend]] ##################################### #fill top slice for normal and first for inverse, fill between polys - if len(lastslice)>0 or (o.inverse and len(poly)>0 and slicesfilled==1): - offs=False - if len(lastslice)>0:#between polys + if not lastslice.is_empty or (o.inverse and not poly.is_empty and slicesfilled==1): + #offs=False + if not lastslice.is_empty:#between polys if o.inverse: - restpoly=poly-lastslice + restpoly=poly.difference(lastslice) else: - restpoly=lastslice-poly#Polygon.Polygon(lastslice) + restpoly=lastslice.difference(poly)#Polygon.Polygon(lastslice) #print('filling between') - if (not o.inverse and len(poly)==0 and slicesfilled>0) or (o.inverse and len(poly)>0 and slicesfilled==1):#first slice fill + if (not o.inverse and poly.is_empty and slicesfilled>0) or (o.inverse and not poly.is_empty and slicesfilled==1):#first slice fill restpoly=lastslice #print('filling first') #print(len(restpoly)) #polyToMesh('fillrest',restpoly,z) - restpoly=outlinePoly(restpoly,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offs) + + 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 len(restpoly)>0: - nchunks=polyToChunks(restpoly,fillz) + while not restpoly.is_empty: + nchunks=shapelyToChunks(restpoly,fillz) #project paths TODO: path projection during waterline is not working if o.waterline_project: nchunks=chunksRefine(nchunks,o) @@ -2904,38 +2935,41 @@ def getPath3axis(context,operation): parentChildDist(lastchunks,nchunks,o) lastchunks=nchunks #slicechunks.extend(polyToChunks(restpoly,z)) - restpoly=outlinePoly(restpoly,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offs) + 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 #''' ##################################### # fill layers and last slice, last slice with inverse is not working yet - inverse millings end now always on 0 so filling ambient does have no sense. - if (slicesfilled>0 and layerstepinc==layerstep) or (not o.inverse and len(poly)>0 and slicesfilled==1) or (o.inverse and len(poly)==0 and slicesfilled>0): + if (slicesfilled>0 and layerstepinc==layerstep) or (not o.inverse and not poly.is_empty and slicesfilled==1) or (o.inverse and poly.is_empty and slicesfilled>0): fillz=z layerstepinc=0 #ilim=1000#TODO:this should be replaced... no limit, just check if the shape grows over limits. - offs=False + #offs=False boundrect=o.ambient#Polygon.Polygon(((o.min.x,o.min.y),(o.min.x,o.max.y),(o.max.x,o.max.y),(o.max.x,o.min.y))) - restpoly=boundrect-poly - if (o.inverse and len(poly)==0 and slicesfilled>0): - restpoly=boundrect-lastslice + restpoly=boundrect.difference(poly) + if (o.inverse and poly.is_empty and slicesfilled>0): + restpoly=boundrect.difference(lastslice) - restpoly=outlinePoly(restpoly,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offs) + 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 len(restpoly)>0: - print(i) - nchunks=polyToChunks(restpoly,fillz) + while not restpoly.is_empty: #'GeometryCollection':#len(restpoly.boundary.coords)>0: + #print(i) + nchunks=shapelyToChunks(restpoly,fillz) ######################### nchunks=limitChunks(nchunks,o, force=True) slicechunks.extend(nchunks) parentChildDist(lastchunks,nchunks,o) lastchunks=nchunks #slicechunks.extend(polyToChunks(restpoly,z)) - restpoly=outlinePoly(restpoly,o.dist_between_paths,o.circle_detail,o.optimize,o.optimize_threshold,offs) + 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 @@ -2953,7 +2987,7 @@ def getPath3axis(context,operation): n=0 while i.sum()>0 and n<10000: i=outlineImageBinary(o,o.dist_between_paths,i,False) - polys=imageToPoly(o,i) + polys=imageToShapely(o,i) for poly in polys: chunks.extend(polyToChunks(poly,z)) n+=1 @@ -3056,7 +3090,7 @@ def getPath3axis(context,operation): for ob in o.objects: polys=getOperationSilhouete(o) for poly in polys: - chunks=polyToChunks(poly,-1) + chunks=shapelyToChunks(poly,-1) chunks = chunksRefine(chunks,o) ''' @@ -3111,7 +3145,7 @@ def getPath3axis(context,operation): filteredPts=[] print('filter points') for p in pts: - if not poly.isInside(p[0],p[1]): + if not poly.contains(sgeometry.Point(p)): vertr.append((True,-1)) else: vertr.append((False,newIdx))