Checkpoint max page cover geometry
This commit is contained in:
@@ -65,6 +65,13 @@ const FAST_FLIP_DURATION = 900;
|
|||||||
const FAST_FLIP_COUNT = 10;
|
const FAST_FLIP_COUNT = 10;
|
||||||
const FAST_FLIP_OVERLAP = 5;
|
const FAST_FLIP_OVERLAP = 5;
|
||||||
const OPEN_SEAM_GAP = 0.003;
|
const OPEN_SEAM_GAP = 0.003;
|
||||||
|
const PAGE_COUNT_MIN = 40;
|
||||||
|
const PAGE_COUNT_STEP = 10;
|
||||||
|
const PAGE_WIDTH = 1.62;
|
||||||
|
const PAGE_DEPTH = 2.24;
|
||||||
|
const COVER_OVERHANG = 0.13;
|
||||||
|
const COVER_SUPPORT_OVERHANG = 0.055;
|
||||||
|
const HINGE_INSET = 0.07;
|
||||||
const SUPPORT_ANGLE_STEPS = 720;
|
const SUPPORT_ANGLE_STEPS = 720;
|
||||||
const SUPPORT_ANGLE_CANDIDATES = Array.from({ length: SUPPORT_ANGLE_STEPS }, (_, sample) => {
|
const SUPPORT_ANGLE_CANDIDATES = Array.from({ length: SUPPORT_ANGLE_STEPS }, (_, sample) => {
|
||||||
const angle = sample / SUPPORT_ANGLE_STEPS * Math.PI * 2;
|
const angle = sample / SUPPORT_ANGLE_STEPS * Math.PI * 2;
|
||||||
@@ -75,6 +82,8 @@ const SUPPORT_ANGLE_CANDIDATES = Array.from({ length: SUPPORT_ANGLE_STEPS }, (_,
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const maximumPageCount = calculateMaximumPageCount();
|
||||||
|
|
||||||
let readingProgress = readInitialProgress();
|
let readingProgress = readInitialProgress();
|
||||||
let pageCount = readInitialPageCount();
|
let pageCount = readInitialPageCount();
|
||||||
let lastLengthError = 0;
|
let lastLengthError = 0;
|
||||||
@@ -83,6 +92,7 @@ let lastBookModel = null;
|
|||||||
let activeSpineHalf = 0.08;
|
let activeSpineHalf = 0.08;
|
||||||
let activeFlips = [];
|
let activeFlips = [];
|
||||||
let pendingPageFlips = 0;
|
let pendingPageFlips = 0;
|
||||||
|
pageCountInput.max = String(maximumPageCount);
|
||||||
progressInput.value = readingProgress.toFixed(3);
|
progressInput.value = readingProgress.toFixed(3);
|
||||||
progressValue.value = readingProgress.toFixed(2);
|
progressValue.value = readingProgress.toFixed(2);
|
||||||
pageCountInput.value = String(pageCount);
|
pageCountInput.value = String(pageCount);
|
||||||
@@ -165,7 +175,7 @@ function readInitialPageCount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function snapPageCount(value) {
|
function snapPageCount(value) {
|
||||||
return THREE.MathUtils.clamp(Math.round(value / 10) * 10, 40, 600);
|
return THREE.MathUtils.clamp(Math.round(value / PAGE_COUNT_STEP) * PAGE_COUNT_STEP, PAGE_COUNT_MIN, maximumPageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setReadingProgress(value) {
|
function setReadingProgress(value) {
|
||||||
@@ -196,8 +206,8 @@ function rebuildBook() {
|
|||||||
|
|
||||||
const coverDepth = 2.30;
|
const coverDepth = 2.30;
|
||||||
const coverThickness = BOOK_PROFILE.coverThickness;
|
const coverThickness = BOOK_PROFILE.coverThickness;
|
||||||
const pageWidth = 1.62;
|
const pageWidth = PAGE_WIDTH;
|
||||||
const pageDepth = 2.24;
|
const pageDepth = PAGE_DEPTH;
|
||||||
const bundleCount = Math.max(4, Math.round(pageCount / 10));
|
const bundleCount = Math.max(4, Math.round(pageCount / 10));
|
||||||
const spineWidth = calculateSpineWidth(bundleCount);
|
const spineWidth = calculateSpineWidth(bundleCount);
|
||||||
const leftCount = calculateLeftBundleCount(bundleCount);
|
const leftCount = calculateLeftBundleCount(bundleCount);
|
||||||
@@ -230,11 +240,9 @@ function addCoverAssembly(pageWidth, depth, thickness, spineWidth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createCoverAssemblyGeometry(pageWidth, depth, thickness, spineWidth) {
|
function createCoverAssemblyGeometry(pageWidth, depth, thickness, spineWidth) {
|
||||||
const overhang = 0.13;
|
|
||||||
const spineHalf = spineWidth * 0.5;
|
const spineHalf = spineWidth * 0.5;
|
||||||
const hingeInset = 0.07;
|
const outerX = spineHalf + pageWidth + COVER_OVERHANG;
|
||||||
const outerX = pageWidth + overhang;
|
const hingeX = spineHalf + HINGE_INSET;
|
||||||
const hingeX = spineHalf + hingeInset;
|
|
||||||
const outerTopY = BOOK_PROFILE.tableY + thickness;
|
const outerTopY = BOOK_PROFILE.tableY + thickness;
|
||||||
const connectionTopY = BOOK_PROFILE.raisedHingeY;
|
const connectionTopY = BOOK_PROFILE.raisedHingeY;
|
||||||
const spineTopY = BOOK_PROFILE.tableY + thickness;
|
const spineTopY = BOOK_PROFILE.tableY + thickness;
|
||||||
@@ -357,6 +365,27 @@ function calculateSpineWidth(bundleCount) {
|
|||||||
return high;
|
return high;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateMaximumPageCount() {
|
||||||
|
let maximum = PAGE_COUNT_MIN;
|
||||||
|
for (let candidate = PAGE_COUNT_MIN; candidate <= 1000; candidate += PAGE_COUNT_STEP) {
|
||||||
|
const bundleCount = Math.max(4, Math.round(candidate / 10));
|
||||||
|
if (!isBundleCountReachable(bundleCount)) break;
|
||||||
|
maximum = candidate;
|
||||||
|
}
|
||||||
|
return maximum;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isBundleCountReachable(bundleCount) {
|
||||||
|
const spineWidth = calculateSpineWidth(bundleCount);
|
||||||
|
const bundleSpacing = calculateBundleSpacing(bundleCount, spineWidth, bundleCount);
|
||||||
|
const topRank = bundleCount - 1;
|
||||||
|
const target = restingTarget(1, PAGE_WIDTH, topRank, bundleCount, bundleSpacing);
|
||||||
|
const anchor = spineCurvePoint(1, spineWidth);
|
||||||
|
const requiredDistance = Math.hypot(target.x - anchor.x, target.y - anchor.y);
|
||||||
|
const verticalRise = target.y - anchor.y;
|
||||||
|
return requiredDistance <= PAGE_WIDTH && verticalRise <= PAGE_WIDTH * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
function calculateBundleSpacing(bundleCount, spineWidth, leftCount) {
|
function calculateBundleSpacing(bundleCount, spineWidth, leftCount) {
|
||||||
const rightCount = bundleCount - leftCount;
|
const rightCount = bundleCount - leftCount;
|
||||||
const stackIntervals = Math.max(0, leftCount - 1) + Math.max(0, rightCount - 1);
|
const stackIntervals = Math.max(0, leftCount - 1) + Math.max(0, rightCount - 1);
|
||||||
@@ -795,8 +824,8 @@ function upwardNormalAt(points, index) {
|
|||||||
function coverTopYAtX(x) {
|
function coverTopYAtX(x) {
|
||||||
const ax = Math.abs(x);
|
const ax = Math.abs(x);
|
||||||
const spineHalf = currentSpineHalf();
|
const spineHalf = currentSpineHalf();
|
||||||
const hingeX = spineHalf + 0.07;
|
const hingeX = spineHalf + HINGE_INSET;
|
||||||
const outerX = 1.62 + 0.055;
|
const outerX = spineHalf + PAGE_WIDTH + COVER_SUPPORT_OVERHANG;
|
||||||
if (ax <= spineHalf) return BOOK_PROFILE.coverThickness;
|
if (ax <= spineHalf) return BOOK_PROFILE.coverThickness;
|
||||||
if (ax <= hingeX) {
|
if (ax <= hingeX) {
|
||||||
const t = (ax - spineHalf) / (hingeX - spineHalf);
|
const t = (ax - spineHalf) / (hingeX - spineHalf);
|
||||||
|
|||||||
@@ -74,6 +74,6 @@
|
|||||||
<button id="fast_forward" type="button">Fast Forward</button>
|
<button id="fast_forward" type="button">Fast Forward</button>
|
||||||
<output id="flip_count">0 / 10</output>
|
<output id="flip_count">0 / 10</output>
|
||||||
</div>
|
</div>
|
||||||
<script type="module" src="/js/webgl-book-shape-lab.js?v=flip-sheet-dimensions-1"></script>
|
<script type="module" src="/js/webgl-book-shape-lab.js?v=max-reachable-cover-width-2"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user