fix: make circular and spiral presets truthful
This commit is contained in:
+42
-21
@@ -1,6 +1,13 @@
|
||||
export const MAX_MICROPHONES = 1024;
|
||||
export const APERTURE_SHAPES = Object.freeze(["rectangle", "ellipse"]);
|
||||
export const PRESET_TYPES = Object.freeze(["grid", "linear", "ring", "spiral", "random"]);
|
||||
export const PRESET_TYPES = Object.freeze([
|
||||
"grid",
|
||||
"linear",
|
||||
"ring",
|
||||
"archimedean",
|
||||
"spiral",
|
||||
"random",
|
||||
]);
|
||||
|
||||
const COORDINATE_SYSTEM = Object.freeze({
|
||||
handedness: "right",
|
||||
@@ -136,41 +143,51 @@ function linearPositions(options, bounds, shape) {
|
||||
});
|
||||
}
|
||||
|
||||
function rectanglePerimeterPosition(ratio, halfWidth, halfHeight) {
|
||||
const width = halfWidth * 2;
|
||||
const height = halfHeight * 2;
|
||||
const perimeter = 2 * (width + height);
|
||||
let distance = ratio * perimeter;
|
||||
if (distance <= width) return [-halfWidth + distance, -halfHeight, 0];
|
||||
distance -= width;
|
||||
if (distance <= height) return [halfWidth, -halfHeight + distance, 0];
|
||||
distance -= height;
|
||||
if (distance <= width) return [halfWidth - distance, halfHeight, 0];
|
||||
distance -= width;
|
||||
return [-halfWidth, halfHeight - distance, 0];
|
||||
function inscribedCircleRadius(bounds) {
|
||||
return Math.min(bounds.halfWidth, bounds.halfHeight);
|
||||
}
|
||||
|
||||
function ringPositions(options, bounds, shape) {
|
||||
function ringPositions(options, bounds) {
|
||||
const count = boundedInteger(options.count ?? 16, "마이크 수", 1, MAX_MICROPHONES);
|
||||
if (count === 1) return [[0, 0, 0]];
|
||||
const radius = inscribedCircleRadius(bounds);
|
||||
return Array.from({ length: count }, (_, index) => {
|
||||
const ratio = index / count;
|
||||
if (shape === "rectangle") {
|
||||
return rectanglePerimeterPosition(ratio, bounds.halfWidth, bounds.halfHeight);
|
||||
}
|
||||
const angle = ratio * Math.PI * 2;
|
||||
return [bounds.halfWidth * Math.cos(angle), bounds.halfHeight * Math.sin(angle), 0];
|
||||
return [radius * Math.cos(angle), radius * Math.sin(angle), 0];
|
||||
});
|
||||
}
|
||||
|
||||
function spiralPositions(options, bounds) {
|
||||
const count = boundedInteger(options.count ?? 32, "마이크 수", 1, MAX_MICROPHONES);
|
||||
if (count === 1) return [[0, 0, 0]];
|
||||
const maximumRadius = inscribedCircleRadius(bounds);
|
||||
return Array.from({ length: count }, (_, index) => {
|
||||
const radius = Math.sqrt((index + 0.5) / count);
|
||||
const angle = index * GOLDEN_ANGLE;
|
||||
return [
|
||||
bounds.halfWidth * radius * Math.cos(angle),
|
||||
bounds.halfHeight * radius * Math.sin(angle),
|
||||
maximumRadius * radius * Math.cos(angle),
|
||||
maximumRadius * radius * Math.sin(angle),
|
||||
0,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
function archimedeanSpiralPositions(options, bounds) {
|
||||
const count = boundedInteger(options.count ?? 32, "마이크 수", 1, MAX_MICROPHONES);
|
||||
if (count === 1) return [[0, 0, 0]];
|
||||
const turns = finiteNumber(options.turns ?? 2.5, "나선 회전 수");
|
||||
if (turns < 0.25 || turns > 32) {
|
||||
throw new RangeError("나선 회전 수는 0.25 이상 32 이하이어야 합니다.");
|
||||
}
|
||||
const maximumRadius = inscribedCircleRadius(bounds);
|
||||
return Array.from({ length: count }, (_, index) => {
|
||||
const ratio = index / (count - 1);
|
||||
const angle = ratio * turns * Math.PI * 2;
|
||||
const radius = maximumRadius * ratio;
|
||||
return [
|
||||
radius * Math.cos(angle),
|
||||
radius * Math.sin(angle),
|
||||
0,
|
||||
];
|
||||
});
|
||||
@@ -286,7 +303,10 @@ export function generatePresetMicrophones(options = {}) {
|
||||
const bounds = presetBounds(options.aperture, options.edgeInsetM);
|
||||
let positions;
|
||||
if (options.type === "linear") positions = linearPositions(options, bounds, shape);
|
||||
else if (options.type === "ring") positions = ringPositions(options, bounds, shape);
|
||||
else if (options.type === "ring") positions = ringPositions(options, bounds);
|
||||
else if (options.type === "archimedean") {
|
||||
positions = archimedeanSpiralPositions(options, bounds);
|
||||
}
|
||||
else if (options.type === "spiral") positions = spiralPositions(options, bounds);
|
||||
else if (options.type === "random") positions = randomPositions(options, bounds, shape);
|
||||
else positions = gridPositions(options, bounds, shape);
|
||||
@@ -320,6 +340,7 @@ export function createArrayDefinition(options = {}) {
|
||||
minimumSpacingM: options.minimumSpacingM,
|
||||
edgeInsetM: options.edgeInsetM,
|
||||
axis: options.axis,
|
||||
turns: options.turns,
|
||||
});
|
||||
return arrayDefinition;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user