This one has be me stumped. This is more of a Math/logic issue then a specific JS issue, but it\'s JS that I am working in and and some point I will need to convert the resu
The answer from @g23 is the basis of this, but I wanted to post the end result I came up with in case anyone wants a complete working system for this dilema.
The end result works by creating a box on the canvas where the user clicks then making 4 boxes around it. Those 4 boxes then use @g23 's original answer to divide it randomly into smaller boxes. The Box in the middle is the solution to having the very 1st divide line cut through the whole image and therefor make it look like two randomly divided boxes that just been stuck side by side. With this new system there will never be a line that cuts all the way across the canvas. I also added a Save button to download the result as well as sliders to control all of the settings and dimensions:
Working Fiddle here
var ImageWidth = 960
var ImageHeight = 540
var direction1 = "x";
var direction2 = "y";
var vert = true;
var LargeVerticalBoxes = parseInt(document.getElementById("lvb").value);
var inner = parseInt(document.getElementById("inner").value);
var smallest = parseInt(document.getElementById("smallest").value);
var totalboxes = "";
var clickBoxWidth = 200;
var clickBoxHeight = 100;
var lineWidth = 5;
var clickBox_xStart = 0;
var clickBox_yStart = 0;
var minSize = 0.1
var maxSize = 0.9
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.canvas.width = ImageWidth;
ctx.canvas.height = ImageHeight;
updateSettings();
canvas.addEventListener('click', function(evt) {
var mousePos = getMousePos(canvas, evt);
//console.log(mousePos.x + ',' + mousePos.y);
clearCanvas();
ctx.beginPath();
calcclickBox(mousePos.x, mousePos.y)
ctx.rect(clickBox_xStart, clickBox_yStart, clickBoxWidth, clickBoxHeight);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath();
reDraw();
}, false);
download_img = function(el) {
var image = canvas.toDataURL("image/png");
el.href = image;
};
function updateSettings() {
lineWidth = parseInt(document.getElementById("linewidth").value,10);
clickBoxWidth = parseInt(document.getElementById("boxWidth").value,10);
clickBoxHeight = parseInt(document.getElementById("boxHeight").value,10);
canvas.width = parseInt(document.getElementById("canWidth").value,10);
canvas.height = parseInt(document.getElementById("canHeight").value,10);
document.getElementById("dispW").innerText = "Width: " + canvas.width;
document.getElementById("dispH").innerText = "Height: " + canvas.height;
document.getElementById("canW").innerText = "Width: " + clickBoxWidth;
document.getElementById("canH").innerText = "Height: " + clickBoxHeight;
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function calcclickBox(x, y) {
clickBox_xStart = x - clickBoxWidth / 2;
clickBox_yStart = y - clickBoxHeight / 2;
clickBoxWidth = clickBoxWidth;
clickBoxHeight = clickBoxHeight;
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function toggle() {
vert = !vert;
if (vert) {
direction1 = "x";
direction2 = "y";
} else {
direction1 = "y";
direction2 = "x";
}
}
function getTotal() {
LargeVerticalBoxes = parseInt(document.getElementById("lvb").value);
inner = parseInt(document.getElementById("inner").value);
smallest = parseInt(document.getElementById("smallest").value);
totalboxes = LargeVerticalBoxes * inner * smallest * 4 + 1
document.getElementById("total").innerText = totalboxes
}
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
/////// big long function that does most of the work //////////
function reDraw() {
getTotal();
// probably play around with this to get better splitting
// maybe split near a mouse click
let splitDimension = (l, n) => {
let splits = [];
let remaining = l;
let x = 0;
for (let i = 0; i < n - 1; i++) {
let r = Math.random();
let seg = remaining * (1 / n);
let s = seg + 0.75 * (0.5 - r) * seg
splits.push([x, s]);
x += s;
remaining -= s;
}
// add the last bit
splits.push([x, remaining])
return splits;
};
// the main idea
class Box {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.boxes = [];
}
draw(ctx) {
ctx.beginPath();
ctx.rect(this.x, this.y, this.w, this.h);
ctx.stroke();
this.boxes.forEach(box => {
box.draw(ctx)
});
}
addBoxes(n, dim) {
let splits;
if (dim == "x") {
// split on width
splits = splitDimension(this.w, n)
// turn the splits into new boxes
this.boxes = splits.map(([x, w]) => {
return new Box(this.x + x, this.y, w, this.h)
});
} else {
// split over height
splits = splitDimension(this.h, n);
// turn the splits into new boxes
this.boxes = splits.map(([y, h]) => {
return new Box(this.x, this.y + y, this.w, h);
})
}
}
}
// let's make some boxes!
let TopRightBox = new Box(clickBox_xStart,
clickBox_yStart,
canvas.width - clickBox_xStart,
-clickBox_yStart);
let BottomRight = new Box(clickBox_xStart + clickBoxWidth,
clickBox_yStart,
canvas.width - clickBox_xStart - clickBoxWidth,
canvas.height - clickBox_yStart);
let BottomLeft = new Box(clickBox_xStart + clickBoxWidth,
clickBox_yStart + clickBoxHeight,
-clickBox_xStart - clickBoxWidth,
canvas.height - clickBox_yStart - clickBoxHeight);
let TopLeft = new Box(0, 0, clickBox_xStart, clickBox_yStart + clickBoxHeight);
TopRightBox.addBoxes(LargeVerticalBoxes, direction1);
BottomRight.addBoxes(LargeVerticalBoxes, direction1);
BottomLeft.addBoxes(LargeVerticalBoxes, direction1);
TopLeft.addBoxes(LargeVerticalBoxes, direction1);
// now add boxes on boxes on boxes
TopRightBox.boxes.forEach(box => {
box.addBoxes(inner, direction2);
// also more boxes
box.boxes.forEach(boxBox => {
boxBox.addBoxes(smallest, direction1);
});
});
BottomRight.boxes.forEach(box => {
box.addBoxes(inner, direction2);
// also more boxes
box.boxes.forEach(boxBox => {
boxBox.addBoxes(smallest, direction1);
});
});
BottomLeft.boxes.forEach(box => {
box.addBoxes(inner, direction2);
// also more boxes
box.boxes.forEach(boxBox => {
boxBox.addBoxes(smallest, direction1);
});
});
TopLeft.boxes.forEach(box => {
box.addBoxes(inner, direction2);
// also more boxes
box.boxes.forEach(boxBox => {
boxBox.addBoxes(smallest, direction1);
});
});
// now draw the boxes!
TopRightBox.draw(ctx);
BottomRight.draw(ctx);
BottomLeft.draw(ctx);
TopLeft.draw(ctx);
document.getElementById("total").innerText = totalboxes
}
click on the canvas to create start box and draw new layout