Я закончил тем, что выбрал свое собственное решение, которое звучало более практично и просто, чем ответ @ arthur . Не уверен, что будет более производительным, хотя. Подводя итог, я сопоставляю, какие блоки перекрываются друг с другом, с помощью вложенного цикла и Path.intersects (path), а затем выполняю другой вложенный цикл, чтобы разделить каждый блок с его перекрывающимися блоками с помощью Path.divide (path), который обрезает исходный путь с тем путем, по которому ты его разделяешь.
Вот мой реальный код, который я использую в своем проекте с комментариями.
setupGrid() {
// Setup block row and column positions
for (let i = 0;i < this.total;i++) {
let x
let y
if (!odd(i)) {
x = firstColumnStartX + (this.size/2)
y = firstColumnStartY + ((i/2) * (this.size + this.gap)) + (this.size/2)
} else {
x = secondColumnStartX + (this.size/2)
y = secondColumnStartY + (Math.floor(i/2) * (this.size + this.gap)) + (this.size/2)
}
this.blocks.push(new paper.Path.Rectangle({
position: [x, y],
size: this.size,
strokeColor: '#ff000050'
}))
}
// Setup array to check what blocks are intersecting
const intersects = []
// Setup empty array with a nested array mapped to other blocks [5 x [5 x undefined]]
for (let i = 0;i < this.total;i++) {
intersects[i] = new Array(this.total).fill(undefined)
}
// Intersect checking
for (let i = 0;i < this.total;i++) {
const block = this.blocks[i]
for (let _i = 0;_i < this.total;_i++) {
const otherBlock = this.blocks[_i]
if (block !== otherBlock && intersects[i][_i] === undefined) {
intersects[_i][i] = intersects[i][_i] = block.intersects(otherBlock)
}
}
}
// First loop through all blocks
for (let i = 0;i < this.total;i++) {
let block = this.blocks[i]
// Then loop through other blocks only if they were intersected with the original block
for (let _i = 0;_i < this.total;_i++) {
const otherBlock = this.blocks[_i]
if (intersects[i][_i]) {
/* divide returns {
pieces: array of separated pieces that would be inside the original block's boundaries
leftoverBlock: what's leftover of the other block if the original block was subtracted from it
} */
const divide = this.divide(block, otherBlock)
block.remove()
otherBlock.remove()
// Override current block with the array of pieces
block = this.blocks[i] = divide.pieces
// Override other block with leftover
this.blocks[_i] = divide.leftoverBlock
// Don't let other block divide with original block since we already did it here
intersects[_i][i] = undefined
}
}
}
// Set random color for each piece to check if successful
for (let i = 0;i < this.blocks.length;i++) {
let block = this.blocks[i]
if (block instanceof Array) {
for (let _i = 0;_i < block.length;_i++) {
block[_i].fillColor = new paper.Color(Math.random(), Math.random(), Math.random(), 0.1)
}
} else {
block.fillColor = new paper.Color(Math.random(), Math.random(), Math.random(), 0.1)
}
}
}
// Divide blockA with blockB and expand
divideBlocks(blockA, blockB, pieces = []) {
const divideA = blockA.divide(blockB)
if (divideA instanceof paper.CompoundPath) {
for (let i = divideA.children.length;i--;) {
const child = divideA.children[i]
child.insertAbove(divideA)
pieces.push(child)
}
divideA.remove()
} else {
pieces.push(divideA)
}
return pieces
}
// Divide group (array of paths) with divider
divideGroup(children, divider, pieces = [], parent) {
for (let i = children.length;i--;) {
const child = children[i]
if (parent) {
child.insertAbove(parent)
}
if (child.intersects(divider)) {
this.divideBlocks(child, divider, pieces)
} else {
pieces.push(child)
}
}
}
// Subtract group (array of paths) from block
subtractGroupFromBlock(block, group) {
let oldBlock
let newBlock = block
for (let i = group.length;i--;) {
const child = group[i]
if (child.intersects(block)) {
newBlock = newBlock.subtract(child)
if (oldBlock) {
oldBlock.remove()
}
oldBlock = newBlock
}
}
return newBlock
}
// Check what kind of divide method to use
divide(blockA, blockB) {
const pieces = []
let leftoverBlock
if (blockA instanceof paper.Path) {
this.divideBlocks(blockA, blockB, pieces)
leftoverBlock = blockB.subtract(blockA)
} else if (blockA instanceof Array) {
this.divideGroup(blockA, blockB, pieces)
leftoverBlock = this.subtractGroupFromBlock(blockB, blockA)
}
return {
pieces,
leftoverBlock
}
}
Мои блоки установлены со случайными цветами для дифференциации каждой фигуры:
Перекрывающиеся блоки перед: https://i.imgur.com/j9ZSUC5.png
[ 118] Перекрывающиеся блоки, разделенные на части: https://i.imgur.com/mc83IH6.png
.
Распределение Гаусса со средним 0 и стандартным отклонением, каждый подразумевает, что среднее число распределения 0 и приблизительно 70% населения, находится в диапазоне [-1, 1]. Проигнорируйте числа, которые являются вне Вашего диапазона - они формируют край 16% приблизительно с обеих сторон.
Возможно, лучшее решение состоит в том, чтобы генерировать распределение с mean=0
и std.dev=0.5
. Это даст Вам распределение приблизительно с 96% значений в диапазоне [-1, 1].
Еще лучшее решение состоит в том, чтобы работать назад как выше и использовать идею, что приблизительно 99,7% значений находится в диапазоне с 3 сигмами: используйте a std.dev = 1/3
. Это почти аннулирует сумму значений not-so-useful, которые Вы получаете. Когда Вы действительно доберетесь один, опустите его.
Конечно, если Вы работаете над математикой интенсивный продукт, все это не переносит значения.
Стандартное отклонение 1,0 влечет за собой, что много значений лягут вне эти [-1,1] диапазон.
Если необходимо остаться в рамках этого диапазона, необходимо использовать другой метод, возможно, nextDouble ().
Распределение Гаусса с Вашими параметрами. имеет плотность e^ (-x^2/2). В целом это имеет форму e^ (линейный (x) +linear (x^2)), что означает любые настройки, которые Вы даете ему, у Вас есть некоторая вероятность получения очень больших и очень небольших чисел.
Вы, вероятно, ищете некоторое другое распределение.
Нормальное распределение дает ненулевое (но "становление чрезвычайно маленьким") вероятность наблюдения значений снаружи [-1, +1] безотносительно различия Вы даете - Вы просто хлюпаете кривая, эффективно.
Вы могли использовать небольшое различие и затем просто выполнить результаты через карту, которая обрезала что-либо меньше чем-1 к-1, и что-либо большее, чем от 1 до 1, но это (строго говоря) больше не будет нормальное распределение.
Что Вам нужно это распределение для из интереса?
Разве нормальное распределение не включает числа, произвольно далекие от среднего, но со все больше маленькими вероятностями? Могло бы случиться так, что Ваши требования (нормальный и ограниченный определенным диапазоном) являются несовместимыми.