kopia lustrzana https://github.com/vilemduha/blendercam
Merge branch 'master' of https://github.com/vilemnovak/blendercam
commit
7c4882d90c
|
|
@ -6,8 +6,13 @@ config/bookmarks.txt
|
|||
/scripts/startup/
|
||||
/scripts/templates_osl/
|
||||
/scripts/templates_py/
|
||||
/scripts/addons/
|
||||
/scripts/addons_contrib/
|
||||
*.spi1d
|
||||
*.pyc
|
||||
*.ocio
|
||||
*.spi3d
|
||||
*.py
|
||||
config/recent-files.txt
|
||||
scripts/addons_contrib/add_mesh_rocks/add_mesh_rocks.xml
|
||||
scripts/addons_contrib/online_mat_lib/material-library/bundled/cycles/wood/rough_pine.bcm
|
||||
|
|
|
|||
|
|
@ -219,8 +219,9 @@ def updateStrategy(o,context):
|
|||
updateExact(o,context)
|
||||
|
||||
def updateCutout(o,context):
|
||||
if o.outlines_count>1:
|
||||
o.use_bridges=False
|
||||
pass;
|
||||
#if o.outlines_count>1:
|
||||
# o.use_bridges=False
|
||||
|
||||
|
||||
def updateExact(o,context):
|
||||
|
|
@ -481,6 +482,9 @@ class camOperation(bpy.types.PropertyGroup):
|
|||
use_bridges = bpy.props.BoolProperty(name="Use bridges",description="use bridges in cutout", default=False, update = updateBridges)
|
||||
bridges_width = bpy.props.FloatProperty(name = 'width of bridges', default=0.002, unit='LENGTH', precision=PRECISION, update = updateBridges)
|
||||
bridges_height = bpy.props.FloatProperty(name = 'height of bridges', description="Height from the bottom of the cutting operation", default=0.0005, unit='LENGTH', precision=PRECISION, update = updateBridges)
|
||||
bridges_group_name = bpy.props.StringProperty(name='Bridges Group', description='Group of curves used as bridges', update=operationValid)
|
||||
|
||||
'''commented this - auto bridges will be generated, but not as a setting of the operation
|
||||
bridges_placement = bpy.props.EnumProperty(name='Bridge placement',
|
||||
items=(
|
||||
('AUTO','Automatic', 'Automatic bridges with a set distance'),
|
||||
|
|
@ -492,6 +496,9 @@ class camOperation(bpy.types.PropertyGroup):
|
|||
|
||||
bridges_per_curve = bpy.props.IntProperty(name="minimum bridges per curve", description="", default=4, min=1, max=512, update = updateBridges)
|
||||
bridges_max_distance = bpy.props.FloatProperty(name = 'Maximum distance between bridges', default=0.08, unit='LENGTH', precision=PRECISION, update = updateBridges)
|
||||
'''
|
||||
group_name = bpy.props.StringProperty(name='Group', description='Object group handled by this operation', update=operationValid)
|
||||
|
||||
#optimisation panel
|
||||
|
||||
#material settings
|
||||
|
|
@ -706,7 +713,7 @@ def get_panels():#convenience function for bot register and unregister functions
|
|||
ops.CamOperationRemove,
|
||||
ops.CamOperationMove,
|
||||
#bridges related
|
||||
ops.CamBridgeAdd,
|
||||
ops.CamBridgesAdd,
|
||||
#5 axis ops
|
||||
ops.CamOrientationAdd,
|
||||
#shape packing
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -295,9 +295,8 @@ class camPathChunk:
|
|||
z=znew
|
||||
i+=1
|
||||
|
||||
|
||||
self.points = chunk.points
|
||||
|
||||
return chunk
|
||||
|
||||
def rampZigZag(self,zstart,zend,o):
|
||||
chunk=camPathChunk([])
|
||||
|
|
@ -428,8 +427,7 @@ class camPathChunk:
|
|||
ratio=1-(traveled/ramplength)
|
||||
znew=zstart-stepdown*ratio
|
||||
chunk.points.append((p2[0],p2[1],max(p2[2],znew)))#max value here is so that it doesn't go below surface in the case of 3d paths
|
||||
|
||||
return chunk
|
||||
self.points=chunk.points
|
||||
#def appendChunk(sorted,ch,o,pos)
|
||||
|
||||
def chunksCoherency(chunks):
|
||||
|
|
@ -542,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
|
||||
|
|
@ -571,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)
|
||||
|
||||
|
|
@ -612,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=[]
|
||||
|
|
@ -633,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')
|
||||
|
|
@ -736,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
|
||||
|
||||
|
|
@ -818,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=[]
|
||||
|
||||
|
|
@ -828,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:
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -664,10 +664,10 @@ class CamOrientationAdd(bpy.types.Operator):
|
|||
return {'FINISHED'}
|
||||
|
||||
|
||||
class CamBridgeAdd(bpy.types.Operator):
|
||||
class CamBridgesAdd(bpy.types.Operator):
|
||||
'''Add orientation to cam operation, for multiaxis operations'''
|
||||
bl_idname = "scene.cam_bridge_add"
|
||||
bl_label = "Add bridge"
|
||||
bl_idname = "scene.cam_bridges_add"
|
||||
bl_label = "Add bridges"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
|
||||
|
|
@ -680,7 +680,7 @@ class CamBridgeAdd(bpy.types.Operator):
|
|||
s=bpy.context.scene
|
||||
a=s.cam_active_operation
|
||||
o=s.cam_operations[a]
|
||||
utils.addBridge(o)
|
||||
utils.addAutoBridges(o)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
|
@ -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'}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,12 +264,85 @@ def polyToMesh(name,p,z):
|
|||
|
||||
return bpy.context.active_object
|
||||
|
||||
def shapelyToMesh(name,p,z):
|
||||
p = Shapely2Polygon(p)
|
||||
ob = polyToMesh(name,p,z)
|
||||
return ob
|
||||
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
|
||||
verts=[]
|
||||
edges=[]
|
||||
vi=0
|
||||
ci=0
|
||||
#for c in p.exterior.coords:
|
||||
|
||||
print(p.type)
|
||||
seq = shapelyToCoords(p)
|
||||
w = 1 # weight
|
||||
|
||||
|
||||
curvedata = bpy.data.curves.new(name=name, type='CURVE')
|
||||
curvedata.dimensions = '3D'
|
||||
|
||||
objectdata = bpy.data.objects.new(name, curvedata)
|
||||
objectdata.location = (0,0,0) #object origin
|
||||
bpy.context.scene.objects.link(objectdata)
|
||||
|
||||
for c in seq:
|
||||
polyline = curvedata.splines.new('POLY')
|
||||
polyline.points.add(len(c)-1)
|
||||
for num in range(len(c)):
|
||||
x, y = c[num][0],c[num][1]
|
||||
|
||||
polyline.points[num].co = (x, y, z, w)
|
||||
|
||||
return objectdata#bpy.context.active_object
|
||||
|
||||
'''#outdated?
|
||||
def orderPoly(polys): #sor poly, do holes e.t.c.
|
||||
p=Polygon.Polygon()
|
||||
levels=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
|
||||
|
|
@ -302,4 +375,5 @@ def orderPoly(polys): #sor poly, do holes e.t.c.
|
|||
p.simplify()
|
||||
li+=1
|
||||
|
||||
return p
|
||||
return p
|
||||
'''
|
||||
|
|
@ -408,13 +408,16 @@ class CAM_OPERATION_PROPERTIES_Panel(CAMButtonsPanel, bpy.types.Panel):
|
|||
layout.prop(ao,'dont_merge')
|
||||
layout.prop(ao,'use_bridges')
|
||||
if ao.use_bridges:
|
||||
layout.prop(ao,'bridges_placement')
|
||||
#layout.prop(ao,'bridges_placement')
|
||||
layout.prop(ao,'bridges_width')
|
||||
layout.prop(ao,'bridges_height')
|
||||
if ao.bridges_placement == 'AUTO':
|
||||
layout.prop(ao,'bridges_per_curve')
|
||||
layout.prop(ao,'bridges_max_distance')
|
||||
|
||||
|
||||
layout.prop_search(ao, "bridges_group_name", bpy.data, "groups")
|
||||
#layout.prop(ao,'bridges_group_name')
|
||||
#if ao.bridges_placement == 'AUTO':
|
||||
# layout.prop(ao,'bridges_per_curve')
|
||||
# layout.prop(ao,'bridges_max_distance')
|
||||
layout.operator("scene.cam_bridges_add", text="Autogenerate bridges")
|
||||
elif ao.strategy=='WATERLINE':
|
||||
layout.prop(ao,'slice_detail')
|
||||
layout.prop(ao,'waterline_fill')
|
||||
|
|
|
|||
|
|
@ -53,15 +53,15 @@ from cam.polygon_utils_cam import *
|
|||
from cam import image_utils
|
||||
from cam.image_utils import *
|
||||
from . import nc
|
||||
from cam.opencamlib.opencamlib import oclSample, oclSamplePoints, oclResampleChunks, oclGetWaterline
|
||||
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
|
||||
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]
|
||||
|
|
@ -90,21 +90,65 @@ def getBoundsWorldspace(obs):
|
|||
maxy=max(maxy,worldCoord.y)
|
||||
maxz=max(maxz,worldCoord.z)
|
||||
else:
|
||||
|
||||
for coord in bb:
|
||||
#this can work badly with some imported curves, don't know why...
|
||||
#worldCoord = mw * Vector((coord[0]/ob.scale.x, coord[1]/ob.scale.y, coord[2]/ob.scale.z))
|
||||
worldCoord =mw * Vector((coord[0], coord[1], coord[2]))
|
||||
minx=min(minx,worldCoord.x)
|
||||
miny=min(miny,worldCoord.y)
|
||||
minz=min(minz,worldCoord.z)
|
||||
maxx=max(maxx,worldCoord.x)
|
||||
maxy=max(maxy,worldCoord.y)
|
||||
maxz=max(maxz,worldCoord.z)
|
||||
|
||||
|
||||
#for coord in bb:
|
||||
for c in ob.data.splines:
|
||||
for p in c.bezier_points:
|
||||
coord=p.co
|
||||
#this can work badly with some imported curves, don't know why...
|
||||
#worldCoord = mw * Vector((coord[0]/ob.scale.x, coord[1]/ob.scale.y, coord[2]/ob.scale.z))
|
||||
worldCoord =mw * Vector((coord[0], coord[1], coord[2]))
|
||||
minx=min(minx,worldCoord.x)
|
||||
miny=min(miny,worldCoord.y)
|
||||
minz=min(minz,worldCoord.z)
|
||||
maxx=max(maxx,worldCoord.x)
|
||||
maxy=max(maxy,worldCoord.y)
|
||||
maxz=max(maxz,worldCoord.z)
|
||||
for p in c.points:
|
||||
coord=p.co
|
||||
#this can work badly with some imported curves, don't know why...
|
||||
#worldCoord = mw * Vector((coord[0]/ob.scale.x, coord[1]/ob.scale.y, coord[2]/ob.scale.z))
|
||||
worldCoord =mw * Vector((coord[0], coord[1], coord[2]))
|
||||
minx=min(minx,worldCoord.x)
|
||||
miny=min(miny,worldCoord.y)
|
||||
minz=min(minz,worldCoord.z)
|
||||
maxx=max(maxx,worldCoord.x)
|
||||
maxy=max(maxy,worldCoord.y)
|
||||
maxz=max(maxz,worldCoord.z)
|
||||
#progress(time.time()-t)
|
||||
return minx,miny,minz,maxx,maxy,maxz
|
||||
|
||||
def getSplineBounds(ob,curve):
|
||||
#progress('getting bounds of object(s)')
|
||||
maxx=maxy=maxz=-10000000
|
||||
minx=miny=minz=10000000
|
||||
mw=ob.matrix_world
|
||||
|
||||
for p in curve.bezier_points:
|
||||
coord=p.co
|
||||
#this can work badly with some imported curves, don't know why...
|
||||
#worldCoord = mw * Vector((coord[0]/ob.scale.x, coord[1]/ob.scale.y, coord[2]/ob.scale.z))
|
||||
worldCoord =mw * Vector((coord[0], coord[1], coord[2]))
|
||||
minx=min(minx,worldCoord.x)
|
||||
miny=min(miny,worldCoord.y)
|
||||
minz=min(minz,worldCoord.z)
|
||||
maxx=max(maxx,worldCoord.x)
|
||||
maxy=max(maxy,worldCoord.y)
|
||||
maxz=max(maxz,worldCoord.z)
|
||||
for p in curve.points:
|
||||
coord=p.co
|
||||
#this can work badly with some imported curves, don't know why...
|
||||
#worldCoord = mw * Vector((coord[0]/ob.scale.x, coord[1]/ob.scale.y, coord[2]/ob.scale.z))
|
||||
worldCoord =mw * Vector((coord[0], coord[1], coord[2]))
|
||||
minx=min(minx,worldCoord.x)
|
||||
miny=min(miny,worldCoord.y)
|
||||
minz=min(minz,worldCoord.z)
|
||||
maxx=max(maxx,worldCoord.x)
|
||||
maxy=max(maxy,worldCoord.y)
|
||||
maxz=max(maxz,worldCoord.z)
|
||||
#progress(time.time()-t)
|
||||
return minx,miny,minz,maxx,maxy,maxz
|
||||
|
||||
def getOperationSources(o):
|
||||
if o.geometry_source=='OBJECT':
|
||||
#bpy.ops.object.select_all(action='DESELECT')
|
||||
|
|
@ -254,7 +298,7 @@ def samplePathLow(o,ch1,ch2,dosample):
|
|||
#print(len(bpath))
|
||||
pixsize=o.pixsize
|
||||
if dosample:
|
||||
if not (o.use_opencamlib and o.use_exact):
|
||||
if not (o.use_opencamlib and o.use_exact):
|
||||
if o.use_exact:
|
||||
cutterdepth=o.cutter_shape.dimensions.z/2
|
||||
for p in bpath.points:
|
||||
|
|
@ -279,10 +323,10 @@ def sampleChunks(o,pathSamples,layers):
|
|||
getAmbient(o)
|
||||
|
||||
if o.use_exact:#prepare collision world
|
||||
if o.use_opencamlib:
|
||||
oclSample(o, pathSamples)
|
||||
cutterdepth=0
|
||||
else:
|
||||
if o.use_opencamlib:
|
||||
oclSample(o, pathSamples)
|
||||
cutterdepth=0
|
||||
else:
|
||||
if o.update_bullet_collision_tag:
|
||||
prepareBulletCollision(o)
|
||||
|
||||
|
|
@ -349,14 +393,14 @@ 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:
|
||||
z=s[2]
|
||||
if minz>z:
|
||||
z=minz
|
||||
newsample=(x,y,z)
|
||||
if o.use_opencamlib and o.use_exact:
|
||||
z=s[2]
|
||||
if minz>z:
|
||||
z=minz
|
||||
newsample=(x,y,z)
|
||||
####sampling
|
||||
elif o.use_exact and not o.use_opencamlib:
|
||||
|
||||
|
|
@ -817,20 +861,20 @@ def doSimulation(name,operations):
|
|||
numpysave(i,iname)
|
||||
i=bpy.data.images.load(iname)
|
||||
createSimulationObject(name,operations,i)
|
||||
|
||||
|
||||
def extendChunks5axis(chunks,o):
|
||||
|
||||
s=bpy.context.scene
|
||||
m=s.cam_machine
|
||||
m=s.cam_machine
|
||||
s=bpy.context.scene
|
||||
free_movement_height = o.free_movement_height# o.max.z +
|
||||
if m.use_position_definitions:# dhull
|
||||
cutterstart=Vector((m.starting_position.x, m.starting_position.y ,max(o.max.z, m.starting_position.z)))#start point for casting
|
||||
else:
|
||||
cutterstart=Vector((0,0,max(o.max.z,free_movement_height)))#start point for casting
|
||||
cutterend=Vector((0,0,o.min.z))
|
||||
oriname=o.name+' orientation'
|
||||
ori=s.objects[oriname]
|
||||
cutterstart=Vector((0,0,max(o.max.z,free_movement_height)))#start point for casting
|
||||
cutterend=Vector((0,0,o.min.z))
|
||||
oriname=o.name+' orientation'
|
||||
ori=s.objects[oriname]
|
||||
#rotationaxes = rotTo2axes(ori.rotation_euler,'CA')#warning-here it allready is reset to 0!!
|
||||
print('rot',o.rotationaxes)
|
||||
a,b=o.rotationaxes#this is all nonsense by now.
|
||||
|
|
@ -846,23 +890,23 @@ def extendChunks5axis(chunks,o):
|
|||
|
||||
|
||||
def chunksToMesh(chunks,o):
|
||||
'''convert sampled chunks to path, optimization of paths'''
|
||||
t=time.time()
|
||||
s=bpy.context.scene
|
||||
m=s.cam_machine
|
||||
'''convert sampled chunks to path, optimization of paths'''
|
||||
t=time.time()
|
||||
s=bpy.context.scene
|
||||
m=s.cam_machine
|
||||
verts=[]
|
||||
|
||||
free_movement_height = o.free_movement_height#o.max.z +
|
||||
|
||||
|
||||
if o.machine_axes=='3':
|
||||
if m.use_position_definitions:
|
||||
origin=(m.starting_position.x, m.starting_position.y, m.starting_position.z)# dhull
|
||||
origin=(m.starting_position.x, m.starting_position.y, m.starting_position.z)# dhull
|
||||
else:
|
||||
origin=(0,0,free_movement_height)
|
||||
|
||||
verts = [origin]
|
||||
if o.machine_axes!='3':
|
||||
verts_rotations=[]#(0,0,0)
|
||||
origin=(0,0,free_movement_height)
|
||||
|
||||
verts = [origin]
|
||||
if o.machine_axes!='3':
|
||||
verts_rotations=[]#(0,0,0)
|
||||
if (o.machine_axes == '5' and o.strategy5axis=='INDEXED') or (o.machine_axes=='4' and o.strategy4axis=='INDEXED'):
|
||||
extendChunks5axis(chunks,o)
|
||||
|
||||
|
|
@ -1035,27 +1079,27 @@ def exportGcodePath(filename,vertslist,operations):
|
|||
elif m.post_processor=='GRAVOS':
|
||||
extension = '.nc'
|
||||
from .nc import gravos as postprocessor
|
||||
elif m.post_processor=='WIN-PC' :
|
||||
extension='.din'
|
||||
from .nc import winpc as postprocessor
|
||||
elif m.post_processor=='WIN-PC' :
|
||||
extension='.din'
|
||||
from .nc import winpc as postprocessor
|
||||
elif m.post_processor=='SHOPBOT MTC':
|
||||
extension='.sbp'
|
||||
from .nc import shopbot_mtc as postprocessor
|
||||
elif m.post_processor=='LYNX_OTTER_O':
|
||||
extension='.nc'
|
||||
from .nc import lynx_otter_o as postprocessor
|
||||
|
||||
if s.unit_settings.system=='METRIC':
|
||||
unitcorr=1000.0
|
||||
elif s.unit_settings.system=='IMPERIAL':
|
||||
unitcorr=1/0.0254;
|
||||
else:
|
||||
unitcorr=1;
|
||||
rotcorr=180.0/pi
|
||||
|
||||
if s.unit_settings.system=='METRIC':
|
||||
unitcorr=1000.0
|
||||
elif s.unit_settings.system=='IMPERIAL':
|
||||
unitcorr=1/0.0254;
|
||||
else:
|
||||
unitcorr=1;
|
||||
rotcorr=180.0/pi
|
||||
|
||||
|
||||
|
||||
def startNewFile():
|
||||
|
||||
def startNewFile():
|
||||
fileindex=''
|
||||
if split:
|
||||
fileindex='_'+str(findex)
|
||||
|
|
@ -1064,15 +1108,15 @@ def exportGcodePath(filename,vertslist,operations):
|
|||
c.file_open(filename)
|
||||
|
||||
#unit system correction
|
||||
###############
|
||||
if s.unit_settings.system=='METRIC':
|
||||
c.metric()
|
||||
elif s.unit_settings.system=='IMPERIAL':
|
||||
###############
|
||||
if s.unit_settings.system=='METRIC':
|
||||
c.metric()
|
||||
elif s.unit_settings.system=='IMPERIAL':
|
||||
c.imperial()
|
||||
|
||||
#start program
|
||||
|
||||
#start program
|
||||
c.program_begin(0,filename)
|
||||
c.flush_nc()
|
||||
c.flush_nc()
|
||||
c.comment('G-code generated with BlenderCAM and NC library')
|
||||
#absolute coordinates
|
||||
c.absolute()
|
||||
|
|
@ -1117,35 +1161,35 @@ def exportGcodePath(filename,vertslist,operations):
|
|||
c.flush_nc()
|
||||
if m.spindle_start_time>0:
|
||||
c.dwell(m.spindle_start_time)
|
||||
c.flush_nc()
|
||||
|
||||
|
||||
# dhull c.feedrate(unitcorr*o.feedrate)
|
||||
|
||||
|
||||
|
||||
c.flush_nc()
|
||||
|
||||
|
||||
# dhull c.feedrate(unitcorr*o.feedrate)
|
||||
|
||||
|
||||
|
||||
#commands=[]
|
||||
m=bpy.context.scene.cam_machine
|
||||
|
||||
millfeedrate=min(o.feedrate,m.feedrate_max)
|
||||
|
||||
millfeedrate=unitcorr*max(millfeedrate,m.feedrate_min)
|
||||
plungefeedrate= millfeedrate*o.plunge_feedrate/100
|
||||
plungefeedrate= millfeedrate*o.plunge_feedrate/100
|
||||
freefeedrate=m.feedrate_max*unitcorr
|
||||
fadjust=False
|
||||
fadjust=False
|
||||
if o.do_simulation_feedrate and mesh.shape_keys!= None and mesh.shape_keys.key_blocks.find('feedrates')!=-1:
|
||||
shapek = mesh.shape_keys.key_blocks['feedrates']
|
||||
fadjust=True
|
||||
|
||||
|
||||
if m.use_position_definitions:# dhull
|
||||
last=Vector((m.starting_position.x, m.starting_position.y, m.starting_position.z))
|
||||
else:
|
||||
last=Vector((0.0,0.0,free_movement_height))#nonsense values so first step of the operation gets written for sure
|
||||
lastrot=Euler((0,0,0))
|
||||
duration=0.0
|
||||
else:
|
||||
last=Vector((0.0,0.0,free_movement_height))#nonsense values so first step of the operation gets written for sure
|
||||
lastrot=Euler((0,0,0))
|
||||
duration=0.0
|
||||
f=millfeedrate
|
||||
fadjustval = 1 # if simulation load data is Not present
|
||||
|
||||
|
||||
downvector= Vector((0,0,-1))
|
||||
plungelimit=(pi/2-o.plunge_angle)
|
||||
|
||||
|
|
@ -1293,16 +1337,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'}
|
||||
|
|
@ -1486,7 +1537,7 @@ def sortChunks(chunks,o):
|
|||
progress('sorting paths')
|
||||
sys.setrecursionlimit(100000)# the getNext() function of CamPathChunk was running out of recursion limits.
|
||||
sortedchunks=[]
|
||||
chunks_to_resample=[]
|
||||
chunks_to_resample=[]
|
||||
|
||||
lastch=None
|
||||
i=len(chunks)
|
||||
|
|
@ -1530,7 +1581,7 @@ def sortChunks(chunks,o):
|
|||
print(len(ch.points))
|
||||
'''
|
||||
|
||||
|
||||
|
||||
sys.setrecursionlimit(1000)
|
||||
if o.strategy!='DRILL':
|
||||
sortedchunks = connectChunksLow(sortedchunks,o)
|
||||
|
|
@ -1632,7 +1683,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:
|
||||
|
|
@ -1649,7 +1700,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
|
||||
|
|
@ -1699,7 +1750,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()
|
||||
|
|
@ -1751,41 +1802,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):
|
||||
|
|
@ -1926,7 +1994,7 @@ def getContainer():
|
|||
container=s.objects['CAM_OBJECTS']
|
||||
|
||||
return container
|
||||
|
||||
'''
|
||||
|
||||
def getSnappingObject(o):
|
||||
s=bpy.context.scene
|
||||
|
|
@ -1980,8 +2048,167 @@ def getBridges(p,o):
|
|||
pos=pos[0],pos[1]
|
||||
bridges.append(pos)
|
||||
return bridges
|
||||
'''
|
||||
|
||||
def addAutoBridges(o):
|
||||
'''attempt to add auto bridges as set of curves'''
|
||||
getOperationSources(o)
|
||||
if not o.onlycurves:
|
||||
o.warnings.append('not curves')
|
||||
return;
|
||||
bridgegroupname=o.bridges_group_name
|
||||
if bridgegroupname == '' or bpy.data.groups.get(bridgegroupname) == None:
|
||||
bridgegroupname = 'bridges_'+o.name
|
||||
bpy.data.groups.new(bridgegroupname)
|
||||
g= bpy.data.groups[bridgegroupname]
|
||||
for ob in o.objects:
|
||||
|
||||
if ob.type=='CURVE':
|
||||
sply = curveToShapely(ob)
|
||||
|
||||
mw=ob.matrix_world
|
||||
for c in ob.data.splines:
|
||||
blength = o.cutter_diameter*1
|
||||
|
||||
minx,miny,minz,maxx,maxy,maxz = getSplineBounds(ob,c)
|
||||
bpy.ops.mesh.primitive_plane_add(radius=blength, view_align=False, enter_editmode=False, location=(0, 0, 0))
|
||||
b=bpy.context.active_object
|
||||
b.name = 'bridge'
|
||||
b.show_name=True
|
||||
b.dimensions.x=o.bridges_width
|
||||
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
|
||||
|
||||
bpy.ops.object.editmode_toggle()
|
||||
bpy.ops.transform.translate(value=(0, blength/2, 0), constraint_axis=(False, True, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
|
||||
bpy.ops.object.editmode_toggle()
|
||||
bpy.ops.object.convert(target='CURVE')
|
||||
|
||||
b.location = (minx+maxx)/2, miny, 0
|
||||
b.rotation_euler.z=pi
|
||||
g.objects.link(b)
|
||||
bpy.ops.object.duplicate(linked=True)
|
||||
b=bpy.context.active_object
|
||||
b.location = (minx+maxx)/2, maxy, 0
|
||||
b.rotation_euler.z=0
|
||||
bpy.ops.object.duplicate(linked=True)
|
||||
b=bpy.context.active_object
|
||||
b.location = minx, (miny+maxy)/2, 0
|
||||
b.rotation_euler.z=pi/2
|
||||
bpy.ops.object.duplicate(linked=True)
|
||||
b=bpy.context.active_object
|
||||
b.location = maxx, (miny+maxy)/2, 0
|
||||
b.rotation_euler.z=-pi/2
|
||||
|
||||
|
||||
|
||||
def addBridges(ch,o):
|
||||
'''this adds bridges to chunks, takes the bridge-objects group and uses the curves inside it as bridges.'''
|
||||
bridgegroupname=o.bridges_group_name
|
||||
bridgegroup=bpy.data.groups[bridgegroupname]
|
||||
|
||||
|
||||
|
||||
#get bridgepoly
|
||||
shapes=[]
|
||||
for ob in bridgegroup.objects:
|
||||
if ob.type == 'CURVE':
|
||||
shapes.extend(curveToShapely(ob))
|
||||
bridgespoly=sops.unary_union(shapes)
|
||||
#buffer the poly, so the bridges are not actually milled...
|
||||
bridgespoly = bridgespoly.buffer(distance = o.cutter_diameter/2.0)
|
||||
####
|
||||
bridgeheight=min(0,o.min.z+o.bridges_height)
|
||||
vi=0
|
||||
#shapelyToCurve('test',bridgespoly,0)
|
||||
newpoints=[]
|
||||
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):
|
||||
i2 = vi+1
|
||||
chp2=ch.points[vi+1]#Vector(ch.points[vi+1])
|
||||
v1=Vector(chp1)
|
||||
v2=Vector(chp2)
|
||||
if v1.z<bridgeheight or v2.z<bridgeheight:
|
||||
v=v2-v1
|
||||
#dist+=v.length
|
||||
p1=sgeometry.Point(chp1)
|
||||
p2=sgeometry.Point(chp1)
|
||||
|
||||
startinside = bridgespoly.contains(p1)
|
||||
endinside = bridgespoly.contains(p2)
|
||||
l=sgeometry.LineString([chp1,chp2])
|
||||
intersections = bridgespoly.boundary.intersection(l)
|
||||
|
||||
itempty = intersections.type == 'GeometryCollection'
|
||||
itpoint = intersections.type == 'Point'
|
||||
itmpoint = intersections.type == 'MultiPoint'
|
||||
|
||||
#print(startinside, endinside,intersections, intersections.type)
|
||||
#print(l,bridgespoly)
|
||||
if not startinside:
|
||||
#print('nothing found')
|
||||
|
||||
newpoints.append(chp1)
|
||||
#elif startinside and endinside and itempty:
|
||||
# newpoints.append((chp1[0],chp1[1],max(chp1[2],bridgeheight)))
|
||||
elif startinside:
|
||||
newpoints.append((chp1[0],chp1[1],max(chp1[2],bridgeheight)))
|
||||
#elif not startinside:
|
||||
# newpoints.append(chp1)
|
||||
cpoints=[]
|
||||
if itpoint:
|
||||
cpoints= [Vector((intersections.x,intersections.y,intersections.z))]
|
||||
elif itmpoint:
|
||||
cpoints=[]
|
||||
for p in intersections:
|
||||
cpoints.append(Vector((p.x,p.y,p.z)))
|
||||
#####sort collisions here :(
|
||||
ncpoints=[]
|
||||
while len(cpoints)>0:
|
||||
mind=10000000
|
||||
mini=-1
|
||||
for i,p in enumerate(cpoints):
|
||||
if min(mind, (p-v1).length)<mind:
|
||||
mini=i
|
||||
mind= (p-v1).length
|
||||
ncpoints.append(cpoints.pop(mini))
|
||||
cpoints = ncpoints
|
||||
#endsorting
|
||||
|
||||
|
||||
if startinside:
|
||||
isinside=True
|
||||
else:
|
||||
isinside=False
|
||||
for cp in cpoints:
|
||||
v3= cp
|
||||
#print(v3)
|
||||
if v.length==0:
|
||||
ratio=1
|
||||
else:
|
||||
fractvect = v3 - v1
|
||||
ratio = fractvect.length/v.length
|
||||
|
||||
collisionz=v1.z+v.z*ratio
|
||||
np1 = (v3.x, v3.y, collisionz)
|
||||
np2 = (v3.x, v3.y, max(collisionz,bridgeheight))
|
||||
if not isinside:
|
||||
newpoints.extend((np1, np2))
|
||||
else:
|
||||
newpoints.extend((np2, np1))
|
||||
isinside = not isinside
|
||||
vi+=1
|
||||
else:
|
||||
newpoints.append(chp1)
|
||||
vi+=1
|
||||
ch.points=newpoints
|
||||
|
||||
|
||||
'''
|
||||
|
||||
def addBridges(ch,o):
|
||||
#this functions adds Bridges to the finished chunks. AUTOMATIC ONLY NOW!
|
||||
if o.bridges_placement == 'AUTO':
|
||||
|
|
@ -2063,6 +2290,8 @@ def addBridges(ch,o):
|
|||
for pi in range(len(insertpoints)-1,-1,-1):
|
||||
ch.points.insert(insertpoints[pi][0],insertpoints[pi][1])
|
||||
|
||||
'''
|
||||
|
||||
###########cutout strategy is completely here:
|
||||
def strategy_cutout( o ):
|
||||
#ob=bpy.context.active_object
|
||||
|
|
@ -2078,7 +2307,7 @@ def strategy_cutout( o ):
|
|||
#print(ch.points)
|
||||
|
||||
if len(ch.points)>2:
|
||||
ch.poly=chunkToPoly(ch)
|
||||
ch.poly=chunkToShapely(ch)
|
||||
#p.addContour(ch.poly)
|
||||
else:
|
||||
chunksFromCurve=[]
|
||||
|
|
@ -2092,11 +2321,12 @@ def strategy_cutout( o ):
|
|||
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)
|
||||
|
|
@ -2130,6 +2360,7 @@ def strategy_cutout( o ):
|
|||
layers=[[o.maxz,o.min.z]]
|
||||
|
||||
print(layers)
|
||||
|
||||
extendorder=[]
|
||||
if o.first_down:#each shape gets either cut all the way to bottom, or every shape gets cut 1 layer, then all again. has to create copies, because same chunks are worked with on more layers usually
|
||||
for chunk in chunksFromCurve:
|
||||
|
|
@ -2148,15 +2379,6 @@ def strategy_cutout( o ):
|
|||
|
||||
chunks=[]
|
||||
|
||||
if o.use_bridges:#add bridges to chunks
|
||||
#bridges=getBridges(p,o)
|
||||
bridgeheight=min(0,o.min.z+o.bridges_height)
|
||||
for chl in extendorder:
|
||||
chunk=chl[0]
|
||||
layer=chl[1]
|
||||
if layer[1]<bridgeheight:
|
||||
addBridges(chunk,o)
|
||||
|
||||
if o.ramp:#add ramps or simply add chunks
|
||||
for chl in extendorder:
|
||||
chunk=chl[0]
|
||||
|
|
@ -2165,9 +2387,19 @@ def strategy_cutout( o ):
|
|||
chunks.append(chunk.rampContour(layer[0],layer[1],o))
|
||||
else:
|
||||
chunks.append(chunk.rampZigZag(layer[0],layer[1],o))
|
||||
else:
|
||||
|
||||
if o.use_bridges:#add bridges to chunks
|
||||
#bridges=getBridges(p,o)
|
||||
bridgeheight=min(0,o.min.z+o.bridges_height)
|
||||
for chl in extendorder:
|
||||
chunks.append(chl[0])
|
||||
chunk=chl[0]
|
||||
layer=chl[1]
|
||||
if layer[1]<bridgeheight:
|
||||
addBridges(chunk,o)
|
||||
|
||||
for chl in extendorder:
|
||||
chunks.append(chl[0])
|
||||
|
||||
|
||||
chunksToMesh(chunks,o)
|
||||
|
||||
|
|
@ -2269,8 +2501,6 @@ def strategy_proj_curve( s, o ):
|
|||
# ch.points=ch.endpoints
|
||||
chunksToMesh(chunks,o)
|
||||
|
||||
#def strategy_pocket( o ):
|
||||
|
||||
|
||||
#this is the main function.
|
||||
#FIXME: split strategies into separate file!
|
||||
|
|
@ -2292,45 +2522,43 @@ def getPath3axis(context, operation):
|
|||
|
||||
elif 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
|
||||
checkCenters=False
|
||||
|
||||
if o.dist_between_paths>o.cutter_diameter/2.0:
|
||||
checkCenters=True
|
||||
o.warnings=o.warnings+'Distance between paths larger\n than cutter radius can result in uncut areas!\n '
|
||||
|
||||
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 checkCenters:
|
||||
contours_before=len(p)
|
||||
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=[]
|
||||
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
|
||||
|
|
@ -2423,10 +2651,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;
|
||||
|
||||
|
|
@ -2487,10 +2715,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)
|
||||
|
|
@ -2499,7 +2728,7 @@ def getPath3axis(context, operation):
|
|||
|
||||
covers=False
|
||||
for poly in o.silhouete:
|
||||
if poly.covers(coutline):
|
||||
if poly.contains(coutline):
|
||||
covers=True
|
||||
break;
|
||||
|
||||
|
|
@ -2592,16 +2821,16 @@ def getPath3axis(context, operation):
|
|||
|
||||
|
||||
elif o.strategy=='WATERLINE' and o.use_opencamlib:
|
||||
getAmbient(o)
|
||||
chunks=[]
|
||||
oclGetWaterline(o, chunks)
|
||||
chunks=limitChunks(chunks,o)
|
||||
getAmbient(o)
|
||||
chunks=[]
|
||||
oclGetWaterline(o, chunks)
|
||||
chunks=limitChunks(chunks,o)
|
||||
if (o.movement_type=='CLIMB' and o.spindle_rotation_direction=='CW') or (o.movement_type=='CONVENTIONAL' and o.spindle_rotation_direction=='CCW'):
|
||||
for ch in chunks:
|
||||
ch.points.reverse()
|
||||
chunksToMesh(chunks,o)
|
||||
|
||||
|
||||
chunksToMesh(chunks,o)
|
||||
|
||||
|
||||
elif o.strategy=='WATERLINE' and not o.use_opencamlib:
|
||||
topdown=True
|
||||
tw=time.time()
|
||||
|
|
@ -2621,7 +2850,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
|
||||
|
|
@ -2636,10 +2865,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:
|
||||
|
|
@ -2651,10 +2880,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:
|
||||
|
|
@ -2678,25 +2907,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)
|
||||
|
|
@ -2708,38 +2939,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
|
||||
|
||||
|
||||
|
|
@ -2757,7 +2991,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
|
||||
|
|
@ -2861,7 +3095,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)
|
||||
|
||||
'''
|
||||
|
|
@ -2916,7 +3150,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))
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue