@mikeabuilder I don't have multiple tools, so it's simple. I never thought we can use slicer for this. In my start script, it tries different area (4 side rects) with different clearances, and calls this macro at the first suitable place. I think you may need to find a larger area so that multiple head can purge at the same time?
var min_x = ... ... var xc = (var.min_x + var.max_x) / 2 var yc = (var.min_y + var.max_y) / 2 var clearance = 40 ; start from 40 / 2 var rect_x1 = 0 var rect_x2 = 0 var rect_y1 = 0 var rect_y2 = 0 while var.clearance > 1 if mod(iterations, 4) == 0 set var.clearance = var.clearance / 2 if var.clearance < 1 break set var.rect_x1 = mod(iterations, 4) == 0 ? var.max_x + var.clearance : move.axes[0].min set var.rect_x2 = mod(iterations, 4) == 1 ? var.min_x - var.clearance : move.axes[1].max set var.rect_y1 = mod(iterations, 4) == 2 ? var.max_y + var.clearance : move.axes[2].min set var.rect_y2 = mod(iterations, 4) == 3 ? var.min_y - var.clearance : move.axes[2].max if var.rect_x1 + global.NOZZLE_DIAMETER > var.rect_x2 continue if var.rect_y1 + global.NOZZLE_DIAMETER > var.rect_y2 continue if (var.rect_x2 - var.rect_x1) * (var.rect_y2 - var.rect_y1) < var.purge_area continue ; Project (xc, yc) into the rect set var.xc = min(max(var.xc, var.rect_x1), var.rect_x2) set var.yc = min(max(var.yc, var.rect_y1), var.rect_y2) ; Shrink the rect to purge_area, close to (xc, yc) and close to a square var xl = max(sqrt(var.purge_area), var.purge_area / (var.rect_y2 - var.rect_y1)) var yl = var.purge_area / var.xl set var.rect_x1 = max(min(var.xc - var.xl / 2, var.rect_x2 - var.xl), var.rect_x1) set var.rect_x2 = var.rect_x1 + var.xl set var.rect_y1 = max(min(var.yc - var.yl / 2, var.rect_y2 - var.yl), var.rect_y1) set var.rect_y2 = var.rect_y1 + var.yl echo "Purge in the rect " ^ {var.rect_x1, var.rect_x2, var.rect_y1, var.rect_y2} M98 P"0:/macros/purge_rect.g" A{var.rect_x1} B{var.rect_x2} C{var.rect_y1} D{var.rect_y2} break if var.clearance < 1 echo "no place to purge"