Shapely replaces Polygon Library - BIG COMMIT

this commit might brake stuff, but it was very needed, to eradicate the
old and not updated Polygon Library with the Shapely lib, which gets
developed more actively.
Lots of functions changed, but so far, things look good, so I commit.
Polishing and deleting old functions come after this.
pull/7/merge
vilemnovak 2015-12-16 18:07:02 +01:00
rodzic a1114f0d5b
commit 46ac43eaa5
6 zmienionych plików z 310 dodań i 136 usunięć

Wyświetl plik

@ -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:

Wyświetl plik

@ -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()

Wyświetl plik

@ -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'}

Wyświetl plik

@ -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

Wyświetl plik

@ -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
return p
'''

Wyświetl plik

@ -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))