Skip to content

Commit

Permalink
Merge pull request #137 from joemarshall/shapely_2
Browse files Browse the repository at this point in the history
Performance improvements (shapely 2 API)
  • Loading branch information
pppalain authored Feb 2, 2024
2 parents dd22059 + 2f21a3d commit 32dab9a
Show file tree
Hide file tree
Showing 13 changed files with 14,942 additions and 15,598 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ forceSyncWithUpstream

.pydevproject
__pycache__/
temp_cam/
temp_cam/
# profiler output files
*.prof
2 changes: 2 additions & 0 deletions scripts/addons/cam/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

from pathlib import Path

USE_PROFILER = False

try:
import shapely
except ImportError:
Expand Down
16 changes: 12 additions & 4 deletions scripts/addons/cam/chunk.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,17 @@ def distStart(self, pos, o):
return dist2d(pos, self._points[0])


def xyDistanceWithin(self,other,cutoff):
if self.poly is None:
self.update_poly()
if other.poly is None:
other.update_poly()
if not self.poly.is_empty and not other.poly.is_empty:
return self.poly.dwithin(other.poly,cutoff)
else:
return _internalXyDistanceTo(self._points,other._points,cutoff)<cutoff


# if cutoff is set, then the first distance < cutoff is returned
def xyDistanceTo(self,other,cutoff=0):
if self.poly is None:
Expand Down Expand Up @@ -828,10 +839,7 @@ def parentChildDist(parents, children, o, distance=None):
for parent in parents:
isrelation = False
if parent != child:
d = parent.xyDistanceTo(child,cutoff=dlim)
if d< dlim:
isrelation = True
if isrelation:
if parent.xyDistanceWithin(child,cutoff=dlim):
parent.children.append(child)
child.parents.append(parent)

Expand Down
11 changes: 3 additions & 8 deletions scripts/addons/cam/gcodepath.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

from cam import chunk
from cam.chunk import *
from cam import USE_PROFILER

from cam import collision
from cam.collision import *
Expand All @@ -59,8 +60,6 @@
from cam.opencamlib.opencamlib import *
from cam.nc import iso

PROFILING=False # set this true to run cprofile on code

def pointonline(a, b, c, tolerence):
b = b - a # convert to vector by subtracting origin
c = c - a
Expand Down Expand Up @@ -543,17 +542,13 @@ async def getPath(context, operation): # should do all path calculations.
print(operation.machine_axes)

if operation.machine_axes == '3':
if PROFILING==True: # profiler
if USE_PROFILER == True: # profiler
import cProfile, pstats, io
pr = cProfile.Profile()
pr.enable()
await getPath3axis(context, operation)
pr.disable()
s = io.StringIO()
sortby = pstats.SortKey.CALLS
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print(s.getvalue())
pr.dump_stats(time.strftime("blendercam_%Y%m%d_%H%M.prof"))
else:
await getPath3axis(context, operation)

Expand Down
181 changes: 108 additions & 73 deletions scripts/addons/cam/image_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
#
# ***** END GPL LICENCE BLOCK *****

import numpy
import math
import time
import numpy
import os
import random
import time

import curve_simplify
import mathutils
Expand Down Expand Up @@ -1027,6 +1028,30 @@ def getResolution(o):
# that's because blender doesn't allow accessing pixels in render :(


def _backup_render_settings(pairs):
properties=[]
for owner,struct_name in pairs:
obj = getattr(owner,struct_name)
if isinstance(obj,bpy.types.bpy_struct):
# structure, backup all properties
obj_value={}
for k in dir(obj):
if not k.startswith("_"):
obj_value[k]=getattr(obj,k)
properties.append(obj_value)
else:
# simple value
properties.append(obj)

def _restore_render_settings(pairs,properties):
for (owner,struct_name),obj_value in zip(pairs,properties):
obj = getattr(owner,struct_name)
if isinstance(obj,bpy.types.bpy_struct):
for k,v in obj_value.items():
setattr(obj,k,v)
else:
setattr(owner,struct_name,obj_value)

def renderSampleImage(o):
t = time.time()
simple.progress('getting zbuffer')
Expand Down Expand Up @@ -1059,96 +1084,106 @@ def renderSampleImage(o):
o.update_zbufferimage_tag = True
if o.update_zbufferimage_tag:
s = bpy.context.scene

# prepare nodes first
s.use_nodes = True
vl = bpy.context.view_layer
n = s.node_tree
r = s.render
r.resolution_x = resx
r.resolution_y = resy
if bpy.app.background:
# in CI we use cycles because it
# works without opengl support

SETTINGS_TO_BACKUP = [
(s.render,"resolution_x"),
(s.render,"resolution_x"),
(s.cycles,"samples"),
(s,"camera"),
(vl,"samples"),
(vl.cycles,"use_denoising"),
(s.world,"mist_settings"),
(r,"resolution_x"),
(r,"resolution_y"),
(r,"resolution_percentage"),
]
for ob in s.objects:
SETTINGS_TO_BACKUP.append((ob,"hide_render"))
backup_settings=None
try:
backup_settings=_backup_render_settings(SETTINGS_TO_BACKUP)
# prepare nodes first
r.resolution_x = resx
r.resolution_y = resy
# use cycles for everything because
# it renders okay on github actions
r.engine = 'CYCLES'
cycles_settings=s.cycles.items()
s.cycles.samples = 1
bpy.context.view_layer.samples=1
vl_settings=bpy.context.view_layer.cycles
vl_settings.use_denoising=False
else:
r.engine = 'BLENDER_EEVEE'


n.links.clear()
n.nodes.clear()
n1 = n.nodes.new('CompositorNodeRLayers')
s.view_layers[n1.layer].use_pass_z=True
n2 = n.nodes.new('CompositorNodeViewer')
n3 = n.nodes.new('CompositorNodeComposite')
n.links.new(n1.outputs[n1.outputs.find('Depth')], n2.inputs[n2.inputs.find('Image')])
n.links.new(n1.outputs[n1.outputs.find('Depth')], n3.inputs[n3.inputs.find('Image')])

n.nodes.active = n2
###################


# resize operation image
o.offset_image= numpy.full(shape=(resx,resy),fill_value=-10,dtype=numpy.double)

# various settings for faster render
r.resolution_percentage = 100

ff = r.image_settings.file_format
cm = r.image_settings.color_mode
r.image_settings.file_format = 'OPEN_EXR'
r.image_settings.color_mode = 'BW'
r.image_settings.color_depth = '32'

# camera settings
camera = s.camera
if camera is None:
vl.samples=1
vl.cycles.use_denoising=False

n.links.clear()
n.nodes.clear()
node_in = n.nodes.new('CompositorNodeRLayers')
s.view_layers[node_in.layer].use_pass_mist=True
mist_settings=s.world.mist_settings
s.world.mist_settings.depth=10.0
s.world.mist_settings.start=0
s.world.mist_settings.falloff="LINEAR"
s.world.mist_settings.height=0
s.world.mist_settings.intensity=0
node_out = n.nodes.new("CompositorNodeOutputFile")
node_out.base_path = os.path.dirname(iname)
node_out.format.file_format = 'OPEN_EXR'
node_out.format.color_mode = 'RGB'
node_out.format.color_depth = '32'
node_out.file_slots.new(os.path.basename(iname))
n.links.new(node_in.outputs[node_in.outputs.find('Mist')], node_out.inputs[-1])
###################

# resize operation image
o.offset_image= numpy.full(shape=(resx,resy),fill_value=-10,dtype=numpy.double)

# various settings for faster render
r.resolution_percentage = 100

# add a new camera settings
bpy.ops.object.camera_add(align='WORLD', enter_editmode=False, location=(0, 0, 0),
rotation=(0, 0, 0))
rotation=(0, 0, 0))
camera = bpy.context.active_object
bpy.context.scene.camera = camera

camera.data.type = 'ORTHO'
camera.data.ortho_scale = max(resx * o.optimisation.pixsize, resy * o.optimisation.pixsize)
camera.location = (o.min.x + sx / 2, o.min.y + sy / 2, 1)
camera.rotation_euler = (0, 0, 0)
# if not o.render_all:#removed in 0.3

h = []
camera.data.type = 'ORTHO'
camera.data.ortho_scale = max(resx * o.optimisation.pixsize, resy * o.optimisation.pixsize)
camera.location = (o.min.x + sx / 2, o.min.y + sy / 2, 1)
camera.rotation_euler = (0, 0, 0)
camera.data.clip_end = 10.0
# if not o.render_all:#removed in 0.3

# ob=bpy.data.objects[o.object_name]
for ob in s.objects:
h.append(ob.hide_render)
ob.hide_render = True
for ob in o.objects:
ob.hide_render = False
h = []

bpy.ops.render.render()
# ob=bpy.data.objects[o.object_name]
for ob in s.objects:
ob.hide_render = True
for ob in o.objects:
ob.hide_render = False

# if not o.render_all:
for id, obs in enumerate(s.objects):
obs.hide_render = h[id]
bpy.ops.render.render()

imgs = bpy.data.images
for isearch in imgs:
if len(isearch.name) >= 13:
if isearch.name[:13] == 'Render Result':
i = isearch
n.nodes.remove(node_out)
n.nodes.remove(node_in)
camera.select_set(True)
bpy.ops.object.delete()

# progress(iname)
i.save_render(iname)
os.replace(iname+"%04d.exr"%(s.frame_current),iname)
finally:
if backup_settings is not None:
_restore_render_settings(SETTINGS_TO_BACKUP,backup_settings)
else:
print("Failed to backup scene settings")

r.image_settings.file_format = ff
r.image_settings.color_mode = cm

i = bpy.data.images.load(iname)
bpy.context.scene.render.engine = 'BLENDERCAM_RENDER'


a = imagetonumpy(i)
a = 1.0 - a
a = 10.0 * a
a= 1.0 - a
o.zbuffer_image = a
o.update_zbufferimage_tag = False

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(Created with grbl post processor 2024/01/26 22:12)
(Created with grbl post processor 2024/01/31 14:46)
G21
(G-code generated with BlenderCAM and NC library)
G17G90
Expand Down Expand Up @@ -376,7 +376,7 @@ X-20Y65
Y-64.999
X-18Y-65.999
Y65
Y66Z-6.899
Y66Z-6.9
G0Z2
X-16
G1Z-6.912F500
Expand Down Expand Up @@ -427,7 +427,7 @@ G1Z-6.912F500
Y-65.999F1000
X18
Y65
Y66Z-6.899
Y66Z-6.9
G0Z2
X20Y65
G1Z-6.912F500
Expand Down
Loading

0 comments on commit 32dab9a

Please sign in to comment.