From a016c536641687fcbc83cf4e69baff84b928a9eb Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 13:24:00 +0100 Subject: [PATCH 01/17] rename package folder to module --- .github/dependabot.yml | 2 +- .github/workflows/publish-npm-github-packages.yml | 8 ++++---- .gitignore | 2 +- app/index.d.ts | 2 +- app/src/store/lensSlice.ts | 2 +- app/src/ui/Graph/useData.ts | 2 +- app/src/ui/LensTable/Table/Row/Aperture.tsx | 2 +- app/src/utilities/useReadFromHash.ts | 2 +- {package => module}/.gitignore | 0 {package => module}/.ts-prunerc | 0 {package => module}/jest.config.js | 0 {package => module}/package.json | 0 {package => module}/src/Lens.test.ts | 0 {package => module}/src/Lens.ts | 0 {package => module}/src/createLensMaker.test.ts | 0 {package => module}/src/createLensMaker.ts | 0 {package => module}/src/index.ts | 0 {package => module}/src/types.d.ts | 0 {package => module}/src/utilities/aperture.test.ts | 0 {package => module}/src/utilities/aperture.ts | 0 .../src/utilities/calculateDepthOfField.test.ts | 0 .../src/utilities/calculateDepthOfField.ts | 0 {package => module}/src/utilities/combineSettings.test.ts | 0 {package => module}/src/utilities/combineSettings.ts | 0 {package => module}/src/utilities/decimalAdjust.test.ts | 0 {package => module}/src/utilities/decimalAdjust.ts | 0 {package => module}/src/utilities/formatFeet.test.ts | 0 {package => module}/src/utilities/formatFeet.ts | 0 {package => module}/src/utilities/objectKeysArray.ts | 0 {package => module}/tsconfig.json | 0 package.json | 8 ++++---- 31 files changed, 15 insertions(+), 15 deletions(-) rename {package => module}/.gitignore (100%) rename {package => module}/.ts-prunerc (100%) rename {package => module}/jest.config.js (100%) rename {package => module}/package.json (100%) rename {package => module}/src/Lens.test.ts (100%) rename {package => module}/src/Lens.ts (100%) rename {package => module}/src/createLensMaker.test.ts (100%) rename {package => module}/src/createLensMaker.ts (100%) rename {package => module}/src/index.ts (100%) rename {package => module}/src/types.d.ts (100%) rename {package => module}/src/utilities/aperture.test.ts (100%) rename {package => module}/src/utilities/aperture.ts (100%) rename {package => module}/src/utilities/calculateDepthOfField.test.ts (100%) rename {package => module}/src/utilities/calculateDepthOfField.ts (100%) rename {package => module}/src/utilities/combineSettings.test.ts (100%) rename {package => module}/src/utilities/combineSettings.ts (100%) rename {package => module}/src/utilities/decimalAdjust.test.ts (100%) rename {package => module}/src/utilities/decimalAdjust.ts (100%) rename {package => module}/src/utilities/formatFeet.test.ts (100%) rename {package => module}/src/utilities/formatFeet.ts (100%) rename {package => module}/src/utilities/objectKeysArray.ts (100%) rename {package => module}/tsconfig.json (100%) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 48972b4a..34fcf7d3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,7 +11,7 @@ updates: interval: daily open-pull-requests-limit: 5 - package-ecosystem: npm - directory: "/package" + directory: "/module" schedule: interval: daily open-pull-requests-limit: 5 diff --git a/.github/workflows/publish-npm-github-packages.yml b/.github/workflows/publish-npm-github-packages.yml index ecbcec86..fea3f239 100644 --- a/.github/workflows/publish-npm-github-packages.yml +++ b/.github/workflows/publish-npm-github-packages.yml @@ -32,8 +32,8 @@ jobs: node-version: '16.x' registry-url: 'https://registry.npmjs.org' - run: yarn install - - run: yarn --cwd package build - - run: yarn --cwd package publish + - run: yarn --cwd module build + - run: yarn --cwd module publish env: NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} @@ -50,7 +50,7 @@ jobs: node-version: '16.x' registry-url: https://npm.pkg.github.com/ - run: yarn install - - run: yarn --cwd package build - - run: yarn --cwd package publish + - run: yarn --cwd module build + - run: yarn --cwd module publish env: NODE_AUTH_TOKEN: ${{secrets.NPM_PUBLISH_TOKEN}} diff --git a/.gitignore b/.gitignore index 421a1f62..2a87c40e 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -package/coverage/ +module/coverage/ dist/ node_modules/ yarn-error.log diff --git a/app/index.d.ts b/app/index.d.ts index 56ce106c..d39adea0 100644 --- a/app/index.d.ts +++ b/app/index.d.ts @@ -16,7 +16,7 @@ interface LensInputs { } interface LensDefinition extends LensInputs { - depthOfField: import('dof').DepthOfFieldDetails + depthOfField: import('../module/dist').DepthOfFieldDetails } type DefaultLensData = Pick diff --git a/app/src/store/lensSlice.ts b/app/src/store/lensSlice.ts index 8dd62850..1fb12837 100644 --- a/app/src/store/lensSlice.ts +++ b/app/src/store/lensSlice.ts @@ -1,4 +1,4 @@ -import { Lens } from 'dof' +import { Lens } from '../../../module/dist' import { compact, defaults } from 'lodash' import { StateCreator } from 'zustand' import areDuplicateLenses from '../utilities/areDuplicateLenses' diff --git a/app/src/ui/Graph/useData.ts b/app/src/ui/Graph/useData.ts index f563f887..98000e95 100644 --- a/app/src/ui/Graph/useData.ts +++ b/app/src/ui/Graph/useData.ts @@ -1,5 +1,5 @@ import { Serie } from '@nivo/line' -import { Lens } from 'dof' +import { Lens } from '../../../../module/dist' import { compact } from 'lodash' import { useMemo } from 'react' import useDoFStore from '../../store' diff --git a/app/src/ui/LensTable/Table/Row/Aperture.tsx b/app/src/ui/LensTable/Table/Row/Aperture.tsx index b9cc4f8b..56353979 100644 --- a/app/src/ui/LensTable/Table/Row/Aperture.tsx +++ b/app/src/ui/LensTable/Table/Row/Aperture.tsx @@ -1,5 +1,5 @@ import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material' -import { apertureMap } from 'dof' +import { apertureMap } from '../../../../../../module/dist' import useDoFStore from '../../../../store' import useIsMobile from '../../../../utilities/useIsMobile' diff --git a/app/src/utilities/useReadFromHash.ts b/app/src/utilities/useReadFromHash.ts index 2005f241..50c99496 100644 --- a/app/src/utilities/useReadFromHash.ts +++ b/app/src/utilities/useReadFromHash.ts @@ -1,4 +1,4 @@ -import { isApertureString } from 'dof' +import { isApertureString } from '../../../module/dist' import { compact } from 'lodash' import { useEffect, useState } from 'react' import useDoFStore from '../store' diff --git a/package/.gitignore b/module/.gitignore similarity index 100% rename from package/.gitignore rename to module/.gitignore diff --git a/package/.ts-prunerc b/module/.ts-prunerc similarity index 100% rename from package/.ts-prunerc rename to module/.ts-prunerc diff --git a/package/jest.config.js b/module/jest.config.js similarity index 100% rename from package/jest.config.js rename to module/jest.config.js diff --git a/package/package.json b/module/package.json similarity index 100% rename from package/package.json rename to module/package.json diff --git a/package/src/Lens.test.ts b/module/src/Lens.test.ts similarity index 100% rename from package/src/Lens.test.ts rename to module/src/Lens.test.ts diff --git a/package/src/Lens.ts b/module/src/Lens.ts similarity index 100% rename from package/src/Lens.ts rename to module/src/Lens.ts diff --git a/package/src/createLensMaker.test.ts b/module/src/createLensMaker.test.ts similarity index 100% rename from package/src/createLensMaker.test.ts rename to module/src/createLensMaker.test.ts diff --git a/package/src/createLensMaker.ts b/module/src/createLensMaker.ts similarity index 100% rename from package/src/createLensMaker.ts rename to module/src/createLensMaker.ts diff --git a/package/src/index.ts b/module/src/index.ts similarity index 100% rename from package/src/index.ts rename to module/src/index.ts diff --git a/package/src/types.d.ts b/module/src/types.d.ts similarity index 100% rename from package/src/types.d.ts rename to module/src/types.d.ts diff --git a/package/src/utilities/aperture.test.ts b/module/src/utilities/aperture.test.ts similarity index 100% rename from package/src/utilities/aperture.test.ts rename to module/src/utilities/aperture.test.ts diff --git a/package/src/utilities/aperture.ts b/module/src/utilities/aperture.ts similarity index 100% rename from package/src/utilities/aperture.ts rename to module/src/utilities/aperture.ts diff --git a/package/src/utilities/calculateDepthOfField.test.ts b/module/src/utilities/calculateDepthOfField.test.ts similarity index 100% rename from package/src/utilities/calculateDepthOfField.test.ts rename to module/src/utilities/calculateDepthOfField.test.ts diff --git a/package/src/utilities/calculateDepthOfField.ts b/module/src/utilities/calculateDepthOfField.ts similarity index 100% rename from package/src/utilities/calculateDepthOfField.ts rename to module/src/utilities/calculateDepthOfField.ts diff --git a/package/src/utilities/combineSettings.test.ts b/module/src/utilities/combineSettings.test.ts similarity index 100% rename from package/src/utilities/combineSettings.test.ts rename to module/src/utilities/combineSettings.test.ts diff --git a/package/src/utilities/combineSettings.ts b/module/src/utilities/combineSettings.ts similarity index 100% rename from package/src/utilities/combineSettings.ts rename to module/src/utilities/combineSettings.ts diff --git a/package/src/utilities/decimalAdjust.test.ts b/module/src/utilities/decimalAdjust.test.ts similarity index 100% rename from package/src/utilities/decimalAdjust.test.ts rename to module/src/utilities/decimalAdjust.test.ts diff --git a/package/src/utilities/decimalAdjust.ts b/module/src/utilities/decimalAdjust.ts similarity index 100% rename from package/src/utilities/decimalAdjust.ts rename to module/src/utilities/decimalAdjust.ts diff --git a/package/src/utilities/formatFeet.test.ts b/module/src/utilities/formatFeet.test.ts similarity index 100% rename from package/src/utilities/formatFeet.test.ts rename to module/src/utilities/formatFeet.test.ts diff --git a/package/src/utilities/formatFeet.ts b/module/src/utilities/formatFeet.ts similarity index 100% rename from package/src/utilities/formatFeet.ts rename to module/src/utilities/formatFeet.ts diff --git a/package/src/utilities/objectKeysArray.ts b/module/src/utilities/objectKeysArray.ts similarity index 100% rename from package/src/utilities/objectKeysArray.ts rename to module/src/utilities/objectKeysArray.ts diff --git a/package/tsconfig.json b/module/tsconfig.json similarity index 100% rename from package/tsconfig.json rename to module/tsconfig.json diff --git a/package.json b/package.json index fffa1c77..f342e023 100644 --- a/package.json +++ b/package.json @@ -3,16 +3,16 @@ "version": "2.1.2", "private": true, "workspaces": [ - "package", + "module", "app" ], "scripts": { - "dev": "yarn --cwd package tsc && yarn --cwd app dev", + "dev": "yarn --cwd module tsc && yarn --cwd app dev", "start": "yarn --cwd app start", "start:ci": "yarn build && yarn --cwd app start", - "build": "yarn --cwd package lint && yarn --cwd package tsc && yarn --cwd app build", + "build": "yarn --cwd module lint && yarn --cwd module tsc && yarn --cwd app build", "clean": "git clean -fdx", - "cover": "yarn --cwd package test --collectCoverage", + "cover": "yarn --cwd module test --collectCoverage", "lint": "yarn workspaces run lint", "preversion": "yarn workspaces run preversion", "postversion": "git push && git push --tags", From c4ea0ccee97886e9a57a8a38e5b964694b8b067d Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 14:14:03 +0100 Subject: [PATCH 02/17] use consts in DoF calc --- module/src/utilities/calculateDepthOfField.ts | 52 +++++++++---------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/module/src/utilities/calculateDepthOfField.ts b/module/src/utilities/calculateDepthOfField.ts index 646c2fd9..5809192a 100644 --- a/module/src/utilities/calculateDepthOfField.ts +++ b/module/src/utilities/calculateDepthOfField.ts @@ -17,54 +17,50 @@ export function calculateDepthOfField( distance: number, imperialUnits: boolean ): DoFResult { - const result: DoFResult = { - dof: 0, - focalLengthEquiv: 0, - eighthDof: 0, - hf: 0, - near: 0, - far: 0, - coc: 0, - } // e.g. 1 foot is 30.48% of 1 meter const unitMultiplier = imperialUnits ? 0.3048 : 1 // Convert to millimeters - distance = distance * 1000 * unitMultiplier + const mmDist = distance * 1000 * unitMultiplier // Get 35mm-equivalent focal length - result.focalLengthEquiv = decimalAdjust(cropFactor * focalLength) + const focalLengthEquiv = decimalAdjust(cropFactor * focalLength) // Convert sensor crop factor to a multiplier - cropFactor = 1 / cropFactor + const sensorMultiplier = 1 / cropFactor - result.coc = Math.round(0.03 * cropFactor * 1000) / 1000 + const CoC = Math.round(0.03 * sensorMultiplier * 1000) / 1000 - result.hf = Math.pow(focalLength, 2) / (aperture * result.coc) + focalLength * 1.0 - result.near = (distance * (result.hf - focalLength)) / (result.hf + distance - 2 * focalLength) - result.far = (distance * (result.hf - focalLength)) / (result.hf - distance) + const HF = Math.pow(focalLength, 2) / (aperture * CoC) + focalLength * 1.0 + const Near = (mmDist * (HF - focalLength)) / (HF + mmDist - 2 * focalLength) + const Far = (mmDist * (HF - focalLength)) / (HF - mmDist) // Undo conversion to millimeters - result.hf = result.hf / 1000.0 / unitMultiplier - result.near = result.near / 1000.0 / unitMultiplier - result.far = result.far / 1000.0 / unitMultiplier - if (result.far <= 0) { - result.far = Infinity - result.dof = Infinity - } else { - result.dof = result.far - result.near - } + const unconvertedNear = Near / 1000.0 / unitMultiplier + const unconvertedFar = Far / 1000.0 / unitMultiplier - result.eighthDof = result.dof / 8 + const isInfinite = unconvertedFar <= 0 + + const dof = isInfinite ? Infinity : unconvertedFar - unconvertedNear + + const result: DoFResult = { + dof, + focalLengthEquiv, + eighthDof: dof / 8, + hf: HF / 1000.0 / unitMultiplier, + near: unconvertedNear, + far: isInfinite ? Infinity : unconvertedFar, + coc: CoC, + } if (imperialUnits) { result.toString = function () { - return formatFeet(result.dof) + return formatFeet(dof) } } else { result.toString = function () { - return `${result.dof}` + return `${dof}` } } From ee95c2ee99c5216dd140cdf897ae7be477dde1b4 Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 14:53:56 +0100 Subject: [PATCH 03/17] tweaks --- app/src/utilities/sensorList.ts | 8 ++- module/src/types.d.ts | 13 ++++ module/src/utilities/calculateAperture.ts | 72 +++++++++++++++++++ .../utilities/calculateDepthOfField.test.ts | 24 +++++++ module/src/utilities/calculateDepthOfField.ts | 32 ++++----- 5 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 module/src/utilities/calculateAperture.ts diff --git a/app/src/utilities/sensorList.ts b/app/src/utilities/sensorList.ts index b52ca77a..e4cb8dac 100644 --- a/app/src/utilities/sensorList.ts +++ b/app/src/utilities/sensorList.ts @@ -30,9 +30,11 @@ const fullList = { name: '1" CCD, Nikon CX, Sony RX100', value: 2.72, }, - iPhone14: { - name: 'iPhone 14 (2022)', - value: 2.86, // 9.8x7.3mm, or 71.54mm^2 + iPhone14Pro: { + name: 'iPhone 14 Pro (2022)', + // https://www.dpreview.com/articles/6110937480 + // 48MP Type 1/1.28 (9.8x7.3mm, or 71.54mm^2) + value: 2.86, isCommon: true, }, BlackmagicCC: { diff --git a/module/src/types.d.ts b/module/src/types.d.ts index 90d34a93..cc05a89a 100644 --- a/module/src/types.d.ts +++ b/module/src/types.d.ts @@ -33,3 +33,16 @@ type DoFResult = { coc: number // Circle of confusion toString: () => string } + +type ApertureResult = { + aperture: number + fStop: ApertureString + dof: number // The length of the depth of field + focalLengthEquiv: number // The focal length in 35mm-equivalency + eighthDof: number // One-eighth of the depth of field + hf: number // Hyperfocal distance + near: number // DoF near limit + far: number // DoF far limit + coc: number // Circle of confusion + toString: () => string +} diff --git a/module/src/utilities/calculateAperture.ts b/module/src/utilities/calculateAperture.ts new file mode 100644 index 00000000..7e2682f0 --- /dev/null +++ b/module/src/utilities/calculateAperture.ts @@ -0,0 +1,72 @@ +import { decimalAdjust } from './decimalAdjust' +import { formatFeet } from './formatFeet' + +/** + * Returns the depth of field characteristics for a given lens' attributes + * + * @param focalLength + * @param aperture + * @param cropFactor + * @param distance + * @param imperialUnits + */ +export function calculateAperture( + focalLength: number, + aperture: number, + cropFactor: number, + distance: number, + imperialUnits: boolean +): DoFResult { + const result: DoFResult = { + dof: 0, + focalLengthEquiv: 0, + eighthDof: 0, + hf: 0, + near: 0, + far: 0, + coc: 0, + } + // e.g. 1 foot is 30.48% of 1 meter + const unitMultiplier = imperialUnits ? 0.3048 : 1 + + // Convert to millimeters + distance = distance * 1000 * unitMultiplier + + // Get 35mm-equivalent focal length + result.focalLengthEquiv = decimalAdjust(cropFactor * focalLength) + + // Convert sensor crop factor to a multiplier + cropFactor = 1 / cropFactor + + result.coc = Math.round(0.03 * cropFactor * 1000) / 1000 + + result.hf = Math.pow(focalLength, 2) / (aperture * result.coc) + focalLength * 1.0 + result.near = (distance * (result.hf - focalLength)) / (result.hf + distance - 2 * focalLength) + result.far = (distance * (result.hf - focalLength)) / (result.hf - distance) + + // Undo conversion to millimeters + result.hf = result.hf / 1000.0 / unitMultiplier + result.near = result.near / 1000.0 / unitMultiplier + result.far = result.far / 1000.0 / unitMultiplier + + if (result.far <= 0) { + result.far = Infinity + result.dof = Infinity + } else { + result.dof = result.far - result.near + } + + result.eighthDof = result.dof / 8 + + if (imperialUnits) { + result.toString = function () { + return formatFeet(result.dof) + } + } else { + result.toString = function () { + return `${result.dof}` + } + } + + return result +} diff --git a/module/src/utilities/calculateDepthOfField.test.ts b/module/src/utilities/calculateDepthOfField.test.ts index 031e521a..5706f654 100644 --- a/module/src/utilities/calculateDepthOfField.test.ts +++ b/module/src/utilities/calculateDepthOfField.test.ts @@ -48,6 +48,30 @@ describe('Calculating the depth of field with calculateDepthOfField', () => { expect(result.coc.toString()).toBe('0.015') }) + test('28mm, f/5, crop factor of 3.02, 7 meters', () => { + // Blackmagic Cine Cam sensor + const result = calculateDepthOfField(28, 5.039684, 3.02, 7, false) + + expect(result.dof).toBe(7.851429380291624) + expect(result.dof.toString()).toBe('7.851429380291624') + expect(result.toString()).toBe(`7.851429380291624`) + + expect(result.eighthDof).toBe(0.981428672536453) + expect(result.eighthDof.toString()).toBe('0.981428672536453') + + expect(result.hf).toBe(15.584530925351668) + expect(result.hf.toString()).toBe('15.584530925351668') + + expect(result.near).toBe(4.833680315786585) + expect(result.near.toString()).toBe('4.833680315786585') + + expect(result.far).toBe(12.685109696078209) + expect(result.far.toString()).toBe('12.685109696078209') + + expect(result.coc).toBe(0.01) + expect(result.coc.toString()).toBe('0.01') + }) + test('such that the far end of the range is infinity', () => { const result = calculateDepthOfField(24, 16, 1, 5, false) diff --git a/module/src/utilities/calculateDepthOfField.ts b/module/src/utilities/calculateDepthOfField.ts index 5809192a..bc802708 100644 --- a/module/src/utilities/calculateDepthOfField.ts +++ b/module/src/utilities/calculateDepthOfField.ts @@ -26,32 +26,28 @@ export function calculateDepthOfField( // Get 35mm-equivalent focal length const focalLengthEquiv = decimalAdjust(cropFactor * focalLength) - // Convert sensor crop factor to a multiplier - const sensorMultiplier = 1 / cropFactor - - const CoC = Math.round(0.03 * sensorMultiplier * 1000) / 1000 - - const HF = Math.pow(focalLength, 2) / (aperture * CoC) + focalLength * 1.0 - const Near = (mmDist * (HF - focalLength)) / (HF + mmDist - 2 * focalLength) - const Far = (mmDist * (HF - focalLength)) / (HF - mmDist) + const cropMultiplier = 1 / cropFactor + const coc = Math.round(0.03 * cropMultiplier * 1000) / 1000 + const mmHF = Math.pow(focalLength, 2) / (aperture * coc) + focalLength * 1.0 + const mmNear = (mmDist * (mmHF - focalLength)) / (mmHF + mmDist - 2 * focalLength) + const mmFar = (mmDist * (mmHF - focalLength)) / (mmHF - mmDist) // Undo conversion to millimeters - const unconvertedNear = Near / 1000.0 / unitMultiplier - const unconvertedFar = Far / 1000.0 / unitMultiplier - - const isInfinite = unconvertedFar <= 0 - - const dof = isInfinite ? Infinity : unconvertedFar - unconvertedNear + const near = mmNear / 1000.0 / unitMultiplier + const trueFar = mmFar / 1000.0 / unitMultiplier + const isInfinite = trueFar <= 0 + const dof = isInfinite ? Infinity : trueFar - near + const far = isInfinite ? Infinity : trueFar const result: DoFResult = { dof, focalLengthEquiv, eighthDof: dof / 8, - hf: HF / 1000.0 / unitMultiplier, - near: unconvertedNear, - far: isInfinite ? Infinity : unconvertedFar, - coc: CoC, + hf: mmHF / 1000.0 / unitMultiplier, + near, + far, + coc, } if (imperialUnits) { From dfa6c7a4701510a8185750d7e3ca8570ee975400 Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 15:38:13 +0100 Subject: [PATCH 04/17] aperture calculation and tests --- module/src/types.d.ts | 10 +-- .../src/utilities/calculateAperture.test.ts | 44 ++++++++++++ module/src/utilities/calculateAperture.ts | 71 ++++++------------- .../utilities/calculateDepthOfField.test.ts | 2 +- 4 files changed, 66 insertions(+), 61 deletions(-) create mode 100644 module/src/utilities/calculateAperture.test.ts diff --git a/module/src/types.d.ts b/module/src/types.d.ts index cc05a89a..22d23256 100644 --- a/module/src/types.d.ts +++ b/module/src/types.d.ts @@ -36,13 +36,5 @@ type DoFResult = { type ApertureResult = { aperture: number - fStop: ApertureString - dof: number // The length of the depth of field - focalLengthEquiv: number // The focal length in 35mm-equivalency - eighthDof: number // One-eighth of the depth of field - hf: number // Hyperfocal distance - near: number // DoF near limit - far: number // DoF far limit - coc: number // Circle of confusion - toString: () => string + fStop: undefined | keyof typeof import('./utilities/aperture').preciseApertureMap } diff --git a/module/src/utilities/calculateAperture.test.ts b/module/src/utilities/calculateAperture.test.ts new file mode 100644 index 00000000..2fdd7235 --- /dev/null +++ b/module/src/utilities/calculateAperture.test.ts @@ -0,0 +1,44 @@ +import { calculateAperture } from './calculateAperture' + +describe('Calculating the depth of field with calculateDepthOfField', () => { + describe('metric units (meters)', () => { + test('DoF 2.584690961719362 meters, 35mm, f/2, crop factor of 1, 5 meters', () => { + const result = calculateAperture(35, 1, 5, 2.584690961719362, 4.021931840567339, false) + + expect(result.aperture).toBe(2) + }) + + test('DoF 11.082093523926748 meters, 50mm, f/1.4, crop factor of 2, 25 meters', () => { + const result = calculateAperture(50, 2, 25, 11.082093523926748, 20.63203625607849, false) + + expect(result.aperture).toBe(1.4142139999999992) + }) + + test('DoF 7.851429380291624 meters, 28mm, f/5, crop factor of 3.02, 7 meters', () => { + // Blackmagic Cine Cam sensor + const result = calculateAperture(28, 3.02, 7, 7.851429380291624, 4.833680315786585, false) + + expect(result.aperture).toBe(5.039684) + }) + + test('such that the far end of the range is infinity', () => { + const result = calculateAperture(24, 1, 5, Infinity, 0.9715025906735751, false) + + expect(result.aperture).toBe(NaN) + }) + }) + + describe('imperial units (feet)', () => { + test('DoF 7.012923816256398 feet, 35mm, f/2, crop factor of 1, 15 feet', () => { + const result = calculateAperture(35, 1, 15, 7.012923816256398, 12.27274548830499, true) + + expect(result.aperture).toBe(2.000000000000001) + }) + + test('DoF 12.634717336600715 feet, 55mm, f/3.2, crop factor of 2.7, 42 feet', () => { + const result = calculateAperture(55, 2.7, 42, 12.634717336600715, 36.61227928000945, true) + + expect(result.aperture).toBe(3.1748020000000055) + }) + }) +}) diff --git a/module/src/utilities/calculateAperture.ts b/module/src/utilities/calculateAperture.ts index 7e2682f0..38d5a755 100644 --- a/module/src/utilities/calculateAperture.ts +++ b/module/src/utilities/calculateAperture.ts @@ -1,71 +1,40 @@ -import { decimalAdjust } from './decimalAdjust' -import { formatFeet } from './formatFeet' +import { getApertureName } from './aperture' /** - * Returns the depth of field characteristics for a given lens' attributes + * Returns the aperture for a given lens' attributes and depth of field * * @param focalLength * @param aperture * @param cropFactor * @param distance + * @param dof + * @param near * @param imperialUnits */ export function calculateAperture( focalLength: number, - aperture: number, cropFactor: number, distance: number, - imperialUnits: boolean -): DoFResult { - const result: DoFResult = { - dof: 0, - focalLengthEquiv: 0, - eighthDof: 0, - hf: 0, - near: 0, - far: 0, - coc: 0, - } + dof: number, + near: number, + imperialUnits?: boolean +): ApertureResult { // e.g. 1 foot is 30.48% of 1 meter const unitMultiplier = imperialUnits ? 0.3048 : 1 // Convert to millimeters - distance = distance * 1000 * unitMultiplier - - // Get 35mm-equivalent focal length - result.focalLengthEquiv = decimalAdjust(cropFactor * focalLength) - - // Convert sensor crop factor to a multiplier - cropFactor = 1 / cropFactor - - result.coc = Math.round(0.03 * cropFactor * 1000) / 1000 - - result.hf = Math.pow(focalLength, 2) / (aperture * result.coc) + focalLength * 1.0 - result.near = (distance * (result.hf - focalLength)) / (result.hf + distance - 2 * focalLength) - result.far = (distance * (result.hf - focalLength)) / (result.hf - distance) - - // Undo conversion to millimeters - result.hf = result.hf / 1000.0 / unitMultiplier - result.near = result.near / 1000.0 / unitMultiplier - result.far = result.far / 1000.0 / unitMultiplier - - if (result.far <= 0) { - result.far = Infinity - result.dof = Infinity - } else { - result.dof = result.far - result.near - } - - result.eighthDof = result.dof / 8 - - if (imperialUnits) { - result.toString = function () { - return formatFeet(result.dof) - } - } else { - result.toString = function () { - return `${result.dof}` - } + const mmDist = distance * 1000 * unitMultiplier + const mmDof = dof * 1000 * unitMultiplier + const mmNear = near * 1000 * unitMultiplier + const mmFar = mmNear + mmDof + const mmHF = (-1 * mmDist * focalLength + mmDist * mmFar) / (-1 * mmDist + mmFar) + const cropMultiplier = 1 / cropFactor + const coc = Math.round(0.03 * cropMultiplier * 1000) / 1000 + const aperture = Math.pow(focalLength, 2) / (coc * mmHF - coc * focalLength) + + const result: ApertureResult = { + aperture, + fStop: getApertureName(aperture), } return result diff --git a/module/src/utilities/calculateDepthOfField.test.ts b/module/src/utilities/calculateDepthOfField.test.ts index 5706f654..2c354ae3 100644 --- a/module/src/utilities/calculateDepthOfField.test.ts +++ b/module/src/utilities/calculateDepthOfField.test.ts @@ -2,7 +2,7 @@ import { calculateDepthOfField } from './calculateDepthOfField' describe('Calculating the depth of field with calculateDepthOfField', () => { describe('metric units (meters)', () => { - test('35mm, f/2, crop factor of 1, 15 meters', () => { + test('35mm, f/2, crop factor of 1, 5 meters', () => { const result = calculateDepthOfField(35, 2, 1, 5, false) expect(result.dof).toBe(2.584690961719362) From 1fdfa3612206cc2bcf1d34ba77e923758afc1be4 Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 17:28:14 +0100 Subject: [PATCH 05/17] calculateAperture takes an object for input --- .../src/utilities/calculateAperture.test.ts | 54 ++++++++++++++++--- module/src/utilities/calculateAperture.ts | 31 ++++++----- 2 files changed, 63 insertions(+), 22 deletions(-) diff --git a/module/src/utilities/calculateAperture.test.ts b/module/src/utilities/calculateAperture.test.ts index 2fdd7235..8c862463 100644 --- a/module/src/utilities/calculateAperture.test.ts +++ b/module/src/utilities/calculateAperture.test.ts @@ -3,26 +3,54 @@ import { calculateAperture } from './calculateAperture' describe('Calculating the depth of field with calculateDepthOfField', () => { describe('metric units (meters)', () => { test('DoF 2.584690961719362 meters, 35mm, f/2, crop factor of 1, 5 meters', () => { - const result = calculateAperture(35, 1, 5, 2.584690961719362, 4.021931840567339, false) + const result = calculateAperture({ + focalLength: 35, + cropFactor: 1, + distance: 5, + dof: 2.584690961719362, + nearLimit: 4.021931840567339, + imperialUnits: false, + }) expect(result.aperture).toBe(2) }) test('DoF 11.082093523926748 meters, 50mm, f/1.4, crop factor of 2, 25 meters', () => { - const result = calculateAperture(50, 2, 25, 11.082093523926748, 20.63203625607849, false) + const result = calculateAperture({ + focalLength: 50, + cropFactor: 2, + distance: 25, + dof: 11.082093523926748, + nearLimit: 20.63203625607849, + imperialUnits: false, + }) expect(result.aperture).toBe(1.4142139999999992) }) test('DoF 7.851429380291624 meters, 28mm, f/5, crop factor of 3.02, 7 meters', () => { // Blackmagic Cine Cam sensor - const result = calculateAperture(28, 3.02, 7, 7.851429380291624, 4.833680315786585, false) + const result = calculateAperture({ + focalLength: 28, + cropFactor: 3.02, + distance: 7, + dof: 7.851429380291624, + nearLimit: 4.833680315786585, + imperialUnits: false, + }) expect(result.aperture).toBe(5.039684) }) test('such that the far end of the range is infinity', () => { - const result = calculateAperture(24, 1, 5, Infinity, 0.9715025906735751, false) + const result = calculateAperture({ + focalLength: 24, + cropFactor: 1, + distance: 5, + dof: Infinity, + nearLimit: 0.9715025906735751, + imperialUnits: false, + }) expect(result.aperture).toBe(NaN) }) @@ -30,13 +58,27 @@ describe('Calculating the depth of field with calculateDepthOfField', () => { describe('imperial units (feet)', () => { test('DoF 7.012923816256398 feet, 35mm, f/2, crop factor of 1, 15 feet', () => { - const result = calculateAperture(35, 1, 15, 7.012923816256398, 12.27274548830499, true) + const result = calculateAperture({ + focalLength: 35, + cropFactor: 1, + distance: 15, + dof: 7.012923816256398, + nearLimit: 12.27274548830499, + imperialUnits: true, + }) expect(result.aperture).toBe(2.000000000000001) }) test('DoF 12.634717336600715 feet, 55mm, f/3.2, crop factor of 2.7, 42 feet', () => { - const result = calculateAperture(55, 2.7, 42, 12.634717336600715, 36.61227928000945, true) + const result = calculateAperture({ + focalLength: 55, + cropFactor: 2.7, + distance: 42, + dof: 12.634717336600715, + nearLimit: 36.61227928000945, + imperialUnits: true, + }) expect(result.aperture).toBe(3.1748020000000055) }) diff --git a/module/src/utilities/calculateAperture.ts b/module/src/utilities/calculateAperture.ts index 38d5a755..ea811f53 100644 --- a/module/src/utilities/calculateAperture.ts +++ b/module/src/utilities/calculateAperture.ts @@ -2,30 +2,29 @@ import { getApertureName } from './aperture' /** * Returns the aperture for a given lens' attributes and depth of field - * - * @param focalLength - * @param aperture - * @param cropFactor - * @param distance - * @param dof - * @param near - * @param imperialUnits */ -export function calculateAperture( - focalLength: number, - cropFactor: number, - distance: number, - dof: number, - near: number, +export function calculateAperture({ + focalLength, + cropFactor, + distance, + dof, + nearLimit, + imperialUnits, +}: { + focalLength: number + cropFactor: number + distance: number + dof: number + nearLimit: number imperialUnits?: boolean -): ApertureResult { +}): ApertureResult { // e.g. 1 foot is 30.48% of 1 meter const unitMultiplier = imperialUnits ? 0.3048 : 1 // Convert to millimeters const mmDist = distance * 1000 * unitMultiplier const mmDof = dof * 1000 * unitMultiplier - const mmNear = near * 1000 * unitMultiplier + const mmNear = nearLimit * 1000 * unitMultiplier const mmFar = mmNear + mmDof const mmHF = (-1 * mmDist * focalLength + mmDist * mmFar) / (-1 * mmDist + mmFar) const cropMultiplier = 1 / cropFactor From 39b100eb31ce67fa112b81e0485dd360509d888c Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 18:46:58 +0100 Subject: [PATCH 06/17] calculate focal length --- module/src/types.d.ts | 5 ++ .../src/utilities/calculateAperture.test.ts | 12 +-- .../utilities/calculateDepthOfField.test.ts | 2 +- module/src/utilities/calculateDepthOfField.ts | 5 +- .../utilities/calculateFocalLength.test.ts | 80 +++++++++++++++++++ module/src/utilities/calculateFocalLength.ts | 44 ++++++++++ 6 files changed, 137 insertions(+), 11 deletions(-) create mode 100644 module/src/utilities/calculateFocalLength.test.ts create mode 100644 module/src/utilities/calculateFocalLength.ts diff --git a/module/src/types.d.ts b/module/src/types.d.ts index 22d23256..722b15d5 100644 --- a/module/src/types.d.ts +++ b/module/src/types.d.ts @@ -34,6 +34,11 @@ type DoFResult = { toString: () => string } +type FocalLengthResult = { + focalLength: number + focalLengthEquiv: number // The focal length in 35mm-equivalency +} + type ApertureResult = { aperture: number fStop: undefined | keyof typeof import('./utilities/aperture').preciseApertureMap diff --git a/module/src/utilities/calculateAperture.test.ts b/module/src/utilities/calculateAperture.test.ts index 8c862463..b2c8661d 100644 --- a/module/src/utilities/calculateAperture.test.ts +++ b/module/src/utilities/calculateAperture.test.ts @@ -1,8 +1,8 @@ import { calculateAperture } from './calculateAperture' -describe('Calculating the depth of field with calculateDepthOfField', () => { +describe('Calculating the depth of field with calculateAperture()', () => { describe('metric units (meters)', () => { - test('DoF 2.584690961719362 meters, 35mm, f/2, crop factor of 1, 5 meters', () => { + test('DoF 2.6 meters, 35mm, f/2, crop factor of 1, 5 meters', () => { const result = calculateAperture({ focalLength: 35, cropFactor: 1, @@ -15,7 +15,7 @@ describe('Calculating the depth of field with calculateDepthOfField', () => { expect(result.aperture).toBe(2) }) - test('DoF 11.082093523926748 meters, 50mm, f/1.4, crop factor of 2, 25 meters', () => { + test('DoF 11 meters, 50mm, f/1.4, crop factor of 2, 25 meters', () => { const result = calculateAperture({ focalLength: 50, cropFactor: 2, @@ -28,7 +28,7 @@ describe('Calculating the depth of field with calculateDepthOfField', () => { expect(result.aperture).toBe(1.4142139999999992) }) - test('DoF 7.851429380291624 meters, 28mm, f/5, crop factor of 3.02, 7 meters', () => { + test('DoF 7.9 meters, 28mm, f/5, crop factor of 3.02, 7 meters', () => { // Blackmagic Cine Cam sensor const result = calculateAperture({ focalLength: 28, @@ -57,7 +57,7 @@ describe('Calculating the depth of field with calculateDepthOfField', () => { }) describe('imperial units (feet)', () => { - test('DoF 7.012923816256398 feet, 35mm, f/2, crop factor of 1, 15 feet', () => { + test('DoF 7 feet, 35mm, f/2, crop factor of 1, 15 feet', () => { const result = calculateAperture({ focalLength: 35, cropFactor: 1, @@ -70,7 +70,7 @@ describe('Calculating the depth of field with calculateDepthOfField', () => { expect(result.aperture).toBe(2.000000000000001) }) - test('DoF 12.634717336600715 feet, 55mm, f/3.2, crop factor of 2.7, 42 feet', () => { + test('DoF 12.6 feet, 55mm, f/3.2, crop factor of 2.7, 42 feet', () => { const result = calculateAperture({ focalLength: 55, cropFactor: 2.7, diff --git a/module/src/utilities/calculateDepthOfField.test.ts b/module/src/utilities/calculateDepthOfField.test.ts index 2c354ae3..3d751647 100644 --- a/module/src/utilities/calculateDepthOfField.test.ts +++ b/module/src/utilities/calculateDepthOfField.test.ts @@ -1,6 +1,6 @@ import { calculateDepthOfField } from './calculateDepthOfField' -describe('Calculating the depth of field with calculateDepthOfField', () => { +describe('Calculating the depth of field with calculateDepthOfField()', () => { describe('metric units (meters)', () => { test('35mm, f/2, crop factor of 1, 5 meters', () => { const result = calculateDepthOfField(35, 2, 1, 5, false) diff --git a/module/src/utilities/calculateDepthOfField.ts b/module/src/utilities/calculateDepthOfField.ts index bc802708..ef8a8335 100644 --- a/module/src/utilities/calculateDepthOfField.ts +++ b/module/src/utilities/calculateDepthOfField.ts @@ -23,9 +23,6 @@ export function calculateDepthOfField( // Convert to millimeters const mmDist = distance * 1000 * unitMultiplier - // Get 35mm-equivalent focal length - const focalLengthEquiv = decimalAdjust(cropFactor * focalLength) - const cropMultiplier = 1 / cropFactor const coc = Math.round(0.03 * cropMultiplier * 1000) / 1000 const mmHF = Math.pow(focalLength, 2) / (aperture * coc) + focalLength * 1.0 @@ -42,7 +39,7 @@ export function calculateDepthOfField( const result: DoFResult = { dof, - focalLengthEquiv, + focalLengthEquiv: decimalAdjust(cropFactor * focalLength), eighthDof: dof / 8, hf: mmHF / 1000.0 / unitMultiplier, near, diff --git a/module/src/utilities/calculateFocalLength.test.ts b/module/src/utilities/calculateFocalLength.test.ts new file mode 100644 index 00000000..e5e83a48 --- /dev/null +++ b/module/src/utilities/calculateFocalLength.test.ts @@ -0,0 +1,80 @@ +import { calculateFocalLength } from './calculateFocalLength' + +describe('Calculating the depth of field with calculateFocalLength()', () => { + describe('metric units (meters)', () => { + test('35mm, f/2, crop factor of 1, 5 meters', () => { + const result = calculateFocalLength({ + nearLimit: 4.021931840567339, + aperture: 2, + cropFactor: 1, + distance: 5, + imperialUnits: false, + }) + + expect(result.focalLength).toBe(35) + }) + + test('50mm, f/1.4, crop factor of 2, 25 meters', () => { + const result = calculateFocalLength({ + nearLimit: 20.63203625607849, + aperture: 1.414214, + cropFactor: 2, + distance: 25, + imperialUnits: false, + }) + + expect(result.focalLength).toBe(50) + }) + + test('28mm, f/5, crop factor of 3.02, 7 meters', () => { + // Blackmagic Cine Cam sensor + const result = calculateFocalLength({ + nearLimit: 4.833680315786585, + aperture: 5.039684, + cropFactor: 3.02, + distance: 7, + imperialUnits: false, + }) + + expect(result.focalLength).toBe(28) + }) + + test('such that the far end of the range is infinity', () => { + const result = calculateFocalLength({ + nearLimit: 0.9715025906735751, + aperture: 16, + cropFactor: 1, + distance: 5, + imperialUnits: false, + }) + + expect(result.focalLength).toBe(24) + }) + }) + + describe('imperial units (feet)', () => { + test('35mm, f/2, crop factor of 1, 15 feet', () => { + const result = calculateFocalLength({ + nearLimit: 12.27274548830499, + aperture: 2, + cropFactor: 1, + distance: 15, + imperialUnits: true, + }) + + expect(result.focalLength).toBe(35) + }) + + test('55mm, f/3.2, crop factor of 2.7, 42 feet', () => { + const result = calculateFocalLength({ + nearLimit: 36.61227928000945, + aperture: 3.174802, + cropFactor: 2.7, + distance: 42, + imperialUnits: true, + }) + + expect(result.focalLength).toBe(55) + }) + }) +}) diff --git a/module/src/utilities/calculateFocalLength.ts b/module/src/utilities/calculateFocalLength.ts new file mode 100644 index 00000000..87c6c124 --- /dev/null +++ b/module/src/utilities/calculateFocalLength.ts @@ -0,0 +1,44 @@ +import { decimalAdjust } from './decimalAdjust' + +/** + * Returns the focal length for a given lens' attributes and depth of field + */ +export function calculateFocalLength({ + nearLimit, + aperture, + cropFactor, + distance, + imperialUnits, +}: { + nearLimit: number + aperture: number + cropFactor: number + distance: number + imperialUnits: boolean +}): FocalLengthResult { + // e.g. 1 foot is 30.48% of 1 meter + const unitMultiplier = imperialUnits ? 0.3048 : 1 + + // Convert to millimeters + const mmDist = distance * 1000 * unitMultiplier + const mmNear = nearLimit * 1000 * unitMultiplier + + const cropMultiplier = 1 / cropFactor + const coc = Math.round(0.03 * cropMultiplier * 1000) / 1000 + + const focalLength = Math.round( + (mmNear * aperture * coc - + Math.sqrt( + Math.pow(mmNear, 2) * Math.pow(aperture, 2) * Math.pow(coc, 2) - + 4 * mmNear * mmDist * aperture * coc * (mmNear - mmDist) + )) / + (2 * (mmNear - mmDist)) + ) + + const result = { + focalLength, + focalLengthEquiv: decimalAdjust(cropFactor * focalLength), + } + + return result +} From a628725296ff59aca8e238229a3175fba0c38c4d Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 18:53:05 +0100 Subject: [PATCH 07/17] move calculators --- module/src/Lens.ts | 2 +- .../{utilities => calculators}/calculateAperture.test.ts | 0 module/src/{utilities => calculators}/calculateAperture.ts | 3 ++- .../calculateDepthOfField.test.ts | 0 .../src/{utilities => calculators}/calculateDepthOfField.ts | 6 +++--- .../{utilities => calculators}/calculateFocalLength.test.ts | 0 .../src/{utilities => calculators}/calculateFocalLength.ts | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) rename module/src/{utilities => calculators}/calculateAperture.test.ts (100%) rename module/src/{utilities => calculators}/calculateAperture.ts (94%) rename module/src/{utilities => calculators}/calculateDepthOfField.test.ts (100%) rename module/src/{utilities => calculators}/calculateDepthOfField.ts (93%) rename module/src/{utilities => calculators}/calculateFocalLength.test.ts (100%) rename module/src/{utilities => calculators}/calculateFocalLength.ts (95%) diff --git a/module/src/Lens.ts b/module/src/Lens.ts index 1a1e0ed9..dcf7dd7d 100644 --- a/module/src/Lens.ts +++ b/module/src/Lens.ts @@ -1,5 +1,5 @@ +import { calculateDepthOfField } from './calculators/calculateDepthOfField' import { combineSettings } from './utilities/combineSettings' -import { calculateDepthOfField } from './utilities/calculateDepthOfField' export const builtInDefaults: DefaultOptions = Object.freeze({ focalLength: 35, diff --git a/module/src/utilities/calculateAperture.test.ts b/module/src/calculators/calculateAperture.test.ts similarity index 100% rename from module/src/utilities/calculateAperture.test.ts rename to module/src/calculators/calculateAperture.test.ts diff --git a/module/src/utilities/calculateAperture.ts b/module/src/calculators/calculateAperture.ts similarity index 94% rename from module/src/utilities/calculateAperture.ts rename to module/src/calculators/calculateAperture.ts index ea811f53..02d12591 100644 --- a/module/src/utilities/calculateAperture.ts +++ b/module/src/calculators/calculateAperture.ts @@ -1,4 +1,4 @@ -import { getApertureName } from './aperture' +import { getApertureName } from '../utilities/aperture' /** * Returns the aperture for a given lens' attributes and depth of field @@ -25,6 +25,7 @@ export function calculateAperture({ const mmDist = distance * 1000 * unitMultiplier const mmDof = dof * 1000 * unitMultiplier const mmNear = nearLimit * 1000 * unitMultiplier + const mmFar = mmNear + mmDof const mmHF = (-1 * mmDist * focalLength + mmDist * mmFar) / (-1 * mmDist + mmFar) const cropMultiplier = 1 / cropFactor diff --git a/module/src/utilities/calculateDepthOfField.test.ts b/module/src/calculators/calculateDepthOfField.test.ts similarity index 100% rename from module/src/utilities/calculateDepthOfField.test.ts rename to module/src/calculators/calculateDepthOfField.test.ts diff --git a/module/src/utilities/calculateDepthOfField.ts b/module/src/calculators/calculateDepthOfField.ts similarity index 93% rename from module/src/utilities/calculateDepthOfField.ts rename to module/src/calculators/calculateDepthOfField.ts index ef8a8335..1f520942 100644 --- a/module/src/utilities/calculateDepthOfField.ts +++ b/module/src/calculators/calculateDepthOfField.ts @@ -1,5 +1,5 @@ -import { decimalAdjust } from './decimalAdjust' -import { formatFeet } from './formatFeet' +import { decimalAdjust } from '../utilities/decimalAdjust' +import { formatFeet } from '../utilities/formatFeet' /** * Returns the depth of field characteristics for a given lens' attributes @@ -30,9 +30,9 @@ export function calculateDepthOfField( const mmFar = (mmDist * (mmHF - focalLength)) / (mmHF - mmDist) // Undo conversion to millimeters - const near = mmNear / 1000.0 / unitMultiplier const trueFar = mmFar / 1000.0 / unitMultiplier + const isInfinite = trueFar <= 0 const dof = isInfinite ? Infinity : trueFar - near const far = isInfinite ? Infinity : trueFar diff --git a/module/src/utilities/calculateFocalLength.test.ts b/module/src/calculators/calculateFocalLength.test.ts similarity index 100% rename from module/src/utilities/calculateFocalLength.test.ts rename to module/src/calculators/calculateFocalLength.test.ts diff --git a/module/src/utilities/calculateFocalLength.ts b/module/src/calculators/calculateFocalLength.ts similarity index 95% rename from module/src/utilities/calculateFocalLength.ts rename to module/src/calculators/calculateFocalLength.ts index 87c6c124..e5fc9852 100644 --- a/module/src/utilities/calculateFocalLength.ts +++ b/module/src/calculators/calculateFocalLength.ts @@ -1,4 +1,4 @@ -import { decimalAdjust } from './decimalAdjust' +import { decimalAdjust } from '../utilities/decimalAdjust' /** * Returns the focal length for a given lens' attributes and depth of field From b11eefe36758e24721fd7f23ce758fe2c45337fa Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 18:57:02 +0100 Subject: [PATCH 08/17] accept object for calculateDof function --- module/src/Lens.ts | 8 +++- .../calculators/calculateDepthOfField.test.ts | 48 ++++++++++++++++--- .../src/calculators/calculateDepthOfField.ts | 18 ++++--- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/module/src/Lens.ts b/module/src/Lens.ts index dcf7dd7d..4a61788f 100644 --- a/module/src/Lens.ts +++ b/module/src/Lens.ts @@ -45,6 +45,12 @@ export class Lens { distance = imperialUnits ? defaultDistanceImperial : defaultDistanceMetric } - return calculateDepthOfField(this.focalLength, this.aperture, this.cropFactor, distance, imperialUnits) + return calculateDepthOfField({ + focalLength: this.focalLength, + aperture: this.aperture, + cropFactor: this.cropFactor, + distance, + imperialUnits, + }) } } diff --git a/module/src/calculators/calculateDepthOfField.test.ts b/module/src/calculators/calculateDepthOfField.test.ts index 3d751647..87f707b4 100644 --- a/module/src/calculators/calculateDepthOfField.test.ts +++ b/module/src/calculators/calculateDepthOfField.test.ts @@ -3,7 +3,13 @@ import { calculateDepthOfField } from './calculateDepthOfField' describe('Calculating the depth of field with calculateDepthOfField()', () => { describe('metric units (meters)', () => { test('35mm, f/2, crop factor of 1, 5 meters', () => { - const result = calculateDepthOfField(35, 2, 1, 5, false) + const result = calculateDepthOfField({ + focalLength: 35, + aperture: 2, + cropFactor: 1, + distance: 5, + imperialUnits: false, + }) expect(result.dof).toBe(2.584690961719362) expect(result.dof.toString()).toBe('2.584690961719362') @@ -26,7 +32,13 @@ describe('Calculating the depth of field with calculateDepthOfField()', () => { }) test('50mm, f/1.4, crop factor of 2, 25 meters', () => { - const result = calculateDepthOfField(50, 1.414214, 2, 25, false) + const result = calculateDepthOfField({ + focalLength: 50, + aperture: 1.414214, + cropFactor: 2, + distance: 25, + imperialUnits: false, + }) expect(result.dof).toBe(11.082093523926748) expect(result.dof.toString()).toBe('11.082093523926748') @@ -50,7 +62,13 @@ describe('Calculating the depth of field with calculateDepthOfField()', () => { test('28mm, f/5, crop factor of 3.02, 7 meters', () => { // Blackmagic Cine Cam sensor - const result = calculateDepthOfField(28, 5.039684, 3.02, 7, false) + const result = calculateDepthOfField({ + focalLength: 28, + aperture: 5.039684, + cropFactor: 3.02, + distance: 7, + imperialUnits: false, + }) expect(result.dof).toBe(7.851429380291624) expect(result.dof.toString()).toBe('7.851429380291624') @@ -73,7 +91,13 @@ describe('Calculating the depth of field with calculateDepthOfField()', () => { }) test('such that the far end of the range is infinity', () => { - const result = calculateDepthOfField(24, 16, 1, 5, false) + const result = calculateDepthOfField({ + focalLength: 24, + aperture: 16, + cropFactor: 1, + distance: 5, + imperialUnits: false, + }) expect(result.dof).toBe(Infinity) expect(result.dof.toString()).toBe('Infinity') @@ -98,7 +122,13 @@ describe('Calculating the depth of field with calculateDepthOfField()', () => { describe('imperial units (feet)', () => { test('35mm, f/2, crop factor of 1, 15 feet', () => { - const result = calculateDepthOfField(35, 2, 1, 15, true) + const result = calculateDepthOfField({ + focalLength: 35, + aperture: 2, + cropFactor: 1, + distance: 15, + imperialUnits: true, + }) expect(result.dof).toBe(7.012923816256398) expect(result.dof.toString()).toBe(`7.012923816256398`) @@ -121,7 +151,13 @@ describe('Calculating the depth of field with calculateDepthOfField()', () => { }) test('55mm, f/3.2, crop factor of 2.7, 42 feet', () => { - const result = calculateDepthOfField(55, 3.174802, 2.7, 42, true) + const result = calculateDepthOfField({ + focalLength: 55, + aperture: 3.174802, + cropFactor: 2.7, + distance: 42, + imperialUnits: true, + }) expect(result.dof).toBe(12.634717336600715) expect(result.dof.toString()).toBe('12.634717336600715') diff --git a/module/src/calculators/calculateDepthOfField.ts b/module/src/calculators/calculateDepthOfField.ts index 1f520942..8266ed07 100644 --- a/module/src/calculators/calculateDepthOfField.ts +++ b/module/src/calculators/calculateDepthOfField.ts @@ -10,13 +10,19 @@ import { formatFeet } from '../utilities/formatFeet' * @param distance * @param imperialUnits */ -export function calculateDepthOfField( - focalLength: number, - aperture: number, - cropFactor: number, - distance: number, +export function calculateDepthOfField({ + focalLength, + aperture, + cropFactor, + distance, + imperialUnits, +}: { + focalLength: number + aperture: number + cropFactor: number + distance: number imperialUnits: boolean -): DoFResult { +}): DoFResult { // e.g. 1 foot is 30.48% of 1 meter const unitMultiplier = imperialUnits ? 0.3048 : 1 From 0d97dc74661170415e041e9a8d3a15c2f57af39c Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 18:57:52 +0100 Subject: [PATCH 09/17] export calculators --- module/src/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/src/index.ts b/module/src/index.ts index 8b745eec..6d800b31 100644 --- a/module/src/index.ts +++ b/module/src/index.ts @@ -3,3 +3,7 @@ export { createLensMaker } from './createLensMaker' export { preciseApertureMap as apertureMap, getApertureName, isApertureString } from './utilities/aperture' type DepthOfFieldDetails = DoFResult export type { DepthOfFieldDetails } + +export { calculateDepthOfField } from './calculators/calculateDepthOfField' +export { calculateAperture } from './calculators/calculateAperture' +export { calculateFocalLength } from './calculators/calculateFocalLength' From bb095fee6f023ab5a8c2af171d8a908f26a802d3 Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 22:23:17 +0100 Subject: [PATCH 10/17] move unit converters to own file --- module/src/calculators/calculateAperture.ts | 11 +++---- .../src/calculators/calculateDepthOfField.ts | 12 ++++---- .../src/calculators/calculateFocalLength.ts | 8 ++--- module/src/utilities/aperture.ts | 14 ++++++++- module/src/utilities/units.ts | 29 +++++++++++++++++++ 5 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 module/src/utilities/units.ts diff --git a/module/src/calculators/calculateAperture.ts b/module/src/calculators/calculateAperture.ts index 02d12591..44e9f173 100644 --- a/module/src/calculators/calculateAperture.ts +++ b/module/src/calculators/calculateAperture.ts @@ -1,4 +1,5 @@ import { getApertureName } from '../utilities/aperture' +import { toMillimeters } from '../utilities/units' /** * Returns the aperture for a given lens' attributes and depth of field @@ -18,13 +19,9 @@ export function calculateAperture({ nearLimit: number imperialUnits?: boolean }): ApertureResult { - // e.g. 1 foot is 30.48% of 1 meter - const unitMultiplier = imperialUnits ? 0.3048 : 1 - - // Convert to millimeters - const mmDist = distance * 1000 * unitMultiplier - const mmDof = dof * 1000 * unitMultiplier - const mmNear = nearLimit * 1000 * unitMultiplier + const mmDist = toMillimeters(distance, imperialUnits) + const mmDof = toMillimeters(dof, imperialUnits) + const mmNear = toMillimeters(nearLimit, imperialUnits) const mmFar = mmNear + mmDof const mmHF = (-1 * mmDist * focalLength + mmDist * mmFar) / (-1 * mmDist + mmFar) diff --git a/module/src/calculators/calculateDepthOfField.ts b/module/src/calculators/calculateDepthOfField.ts index 8266ed07..4aa85411 100644 --- a/module/src/calculators/calculateDepthOfField.ts +++ b/module/src/calculators/calculateDepthOfField.ts @@ -1,5 +1,6 @@ import { decimalAdjust } from '../utilities/decimalAdjust' import { formatFeet } from '../utilities/formatFeet' +import { fromMillimeters, toMillimeters } from '../utilities/units' /** * Returns the depth of field characteristics for a given lens' attributes @@ -23,11 +24,8 @@ export function calculateDepthOfField({ distance: number imperialUnits: boolean }): DoFResult { - // e.g. 1 foot is 30.48% of 1 meter - const unitMultiplier = imperialUnits ? 0.3048 : 1 - // Convert to millimeters - const mmDist = distance * 1000 * unitMultiplier + const mmDist = toMillimeters(distance, imperialUnits) const cropMultiplier = 1 / cropFactor const coc = Math.round(0.03 * cropMultiplier * 1000) / 1000 @@ -36,8 +34,8 @@ export function calculateDepthOfField({ const mmFar = (mmDist * (mmHF - focalLength)) / (mmHF - mmDist) // Undo conversion to millimeters - const near = mmNear / 1000.0 / unitMultiplier - const trueFar = mmFar / 1000.0 / unitMultiplier + const near = fromMillimeters(mmNear, imperialUnits) + const trueFar = fromMillimeters(mmFar, imperialUnits) const isInfinite = trueFar <= 0 const dof = isInfinite ? Infinity : trueFar - near @@ -47,7 +45,7 @@ export function calculateDepthOfField({ dof, focalLengthEquiv: decimalAdjust(cropFactor * focalLength), eighthDof: dof / 8, - hf: mmHF / 1000.0 / unitMultiplier, + hf: fromMillimeters(mmHF, imperialUnits), near, far, coc, diff --git a/module/src/calculators/calculateFocalLength.ts b/module/src/calculators/calculateFocalLength.ts index e5fc9852..8e83aefa 100644 --- a/module/src/calculators/calculateFocalLength.ts +++ b/module/src/calculators/calculateFocalLength.ts @@ -1,4 +1,5 @@ import { decimalAdjust } from '../utilities/decimalAdjust' +import { toMillimeters } from '../utilities/units' /** * Returns the focal length for a given lens' attributes and depth of field @@ -16,12 +17,9 @@ export function calculateFocalLength({ distance: number imperialUnits: boolean }): FocalLengthResult { - // e.g. 1 foot is 30.48% of 1 meter - const unitMultiplier = imperialUnits ? 0.3048 : 1 - // Convert to millimeters - const mmDist = distance * 1000 * unitMultiplier - const mmNear = nearLimit * 1000 * unitMultiplier + const mmDist = toMillimeters(distance, imperialUnits) + const mmNear = toMillimeters(nearLimit, imperialUnits) const cropMultiplier = 1 / cropFactor const coc = Math.round(0.03 * cropMultiplier * 1000) / 1000 diff --git a/module/src/utilities/aperture.ts b/module/src/utilities/aperture.ts index face240d..a590ad76 100644 --- a/module/src/utilities/aperture.ts +++ b/module/src/utilities/aperture.ts @@ -71,13 +71,25 @@ function getPreciseAperture(humanValue: string): number | undefined { return } +/** + * Finds the nearest known aperture to a given number + * @example nearestValue(1.99) // 2.0 + * + * @param {number} targetAperture the ideal value for which the nearest or equal should be found + */ +const nearestValue = (targetAperture: number) => + sortedValues.reduce((p, n) => (Math.abs(p) > Math.abs(n - targetAperture) ? n - targetAperture : p), Infinity) + + targetAperture + /** * Takes a numeric value and returns a human-friendly string that is equivalent * @example 5.039684 => 'f/5' */ export function getApertureName(value: number): keyof typeof preciseApertureMap | undefined { + const asKnownAperture = nearestValue(value) + return objectKeysArray(preciseApertureMap).find((key) => { - return preciseApertureMap[key] === value + return preciseApertureMap[key] === asKnownAperture }) } diff --git a/module/src/utilities/units.ts b/module/src/utilities/units.ts new file mode 100644 index 00000000..ee9bb705 --- /dev/null +++ b/module/src/utilities/units.ts @@ -0,0 +1,29 @@ +/** + * Returns a number that a value can be multiplied by to assure the value is metric + * + * @param imperialUnits true if value is in feet instead of meters + */ +function getUnitMultiplier(imperialUnits = false): number { + // e.g. 1 foot is 30.48% of 1 meter + return imperialUnits ? 0.3048 : 1 +} + +/** + * Convert a value from meters or feet, to millimeters + * + * @param value value in meters or feet + * @param imperialUnits true if value is in feet instead of meters + */ +export function toMillimeters(value: number, imperialUnits = false): number { + return value * 1000 * getUnitMultiplier(imperialUnits) +} + +/** + * Convert a value from millimeters to meters or feet + * + * @param value value in millimeters + * @param imperialUnits true if value should be in feet instead of meters + */ +export function fromMillimeters(value: number, imperialUnits = false): number { + return value / 1000.0 / getUnitMultiplier(imperialUnits) +} From a970d8a53b90f96d7bc4c2f45902f5507fd8b8b1 Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 11 Feb 2023 22:27:34 +0100 Subject: [PATCH 11/17] bump version number to 2.2.0 --- .eslintignore | 1 - module/package.json | 2 +- package.json | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.eslintignore b/.eslintignore index 68203872..3c3629e6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1 @@ node_modules -gui diff --git a/module/package.json b/module/package.json index 9aa0f658..6e37220a 100644 --- a/module/package.json +++ b/module/package.json @@ -1,7 +1,7 @@ { "name": "dof", "description": "Depth-of-field calculator for comparing camera lenses", - "version": "2.1.2", + "version": "2.2.0", "repository": { "type": "git", "url": "https://github.com/patik/dof.git" diff --git a/package.json b/package.json index f342e023..e2b9d22c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@patik/dof", - "version": "2.1.2", + "version": "2.2.0", "private": true, "workspaces": [ "module", From 32f105cb14a2c022f2203cad7468f957824e8ae0 Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Mon, 13 Feb 2023 08:51:02 +0100 Subject: [PATCH 12/17] added calculateCropFactor --- .../calculators/calculateCropFactor.test.ts | 73 +++++++++++++++++++ module/src/calculators/calculateCropFactor.ts | 38 ++++++++++ module/src/types.d.ts | 4 + 3 files changed, 115 insertions(+) create mode 100644 module/src/calculators/calculateCropFactor.test.ts create mode 100644 module/src/calculators/calculateCropFactor.ts diff --git a/module/src/calculators/calculateCropFactor.test.ts b/module/src/calculators/calculateCropFactor.test.ts new file mode 100644 index 00000000..c1574f41 --- /dev/null +++ b/module/src/calculators/calculateCropFactor.test.ts @@ -0,0 +1,73 @@ +import { calculateCropFactor } from './calculateCropFactor' + +describe('Calculating the depth of field with calculateCropFactor()', () => { + describe('metric units (meters)', () => { + test('35mm, f/2, crop factor of 1, 5 meters', () => { + const result = calculateCropFactor({ + dof: 2.584690961719362, + nearLimit: 4.021931840567339, + focalLength: 35, + aperture: 2, + distance: 5, + imperialUnits: false, + }) + + expect(result.cropFactor).toBe(1) + }) + + test('50mm, f/1.4, crop factor of 2, 25 meters', () => { + const result = calculateCropFactor({ + dof: 11.082093523926748, + nearLimit: 20.63203625607849, + focalLength: 50, + aperture: 1.414214, + distance: 25, + imperialUnits: false, + }) + + expect(result.cropFactor).toBe(2) + }) + + test('28mm, f/5, crop factor of 3.02, 7 meters', () => { + // Blackmagic Cine Cam sensor + const result = calculateCropFactor({ + focalLength: 28, + aperture: 5.039684, + dof: 7.851429380291624, + nearLimit: 4.833680315786585, + distance: 7, + imperialUnits: false, + }) + + expect(result.cropFactor).toBe(3) + }) + }) + + describe('imperial units (feet)', () => { + test('35mm, f/2, crop factor of 1, 15 feet', () => { + const result = calculateCropFactor({ + focalLength: 35, + aperture: 2, + nearLimit: 12.27274548830499, + dof: 7.012923816256398, + distance: 15, + imperialUnits: true, + }) + + expect(result.cropFactor).toBe(1) + }) + + test('55mm, f/3.2, crop factor of 2.7, 42 feet', () => { + const result = calculateCropFactor({ + focalLength: 55, + aperture: 3.174802, + dof: 12.634717336600715, + nearLimit: 36.61227928000945, + distance: 42, + imperialUnits: true, + }) + + expect(result.cropFactor).toBe(2.727) + }) + }) +}) diff --git a/module/src/calculators/calculateCropFactor.ts b/module/src/calculators/calculateCropFactor.ts new file mode 100644 index 00000000..896bde1e --- /dev/null +++ b/module/src/calculators/calculateCropFactor.ts @@ -0,0 +1,38 @@ +import { toMillimeters } from '../utilities/units' + +/** + * Returns the depth of field characteristics for a given lens' attributes + * + * @param focalLength + * @param aperture + * @param cropFactor + * @param distance + * @param imperialUnits + */ +export function calculateCropFactor({ + nearLimit, + dof, + focalLength, + aperture, + distance, + imperialUnits, +}: { + nearLimit: number + dof: number + focalLength: number + aperture: number + distance: number + imperialUnits: boolean +}): CropFactorResult { + const mmDist = toMillimeters(distance, imperialUnits) + const mmDof = toMillimeters(dof, imperialUnits) + const mmNear = toMillimeters(nearLimit, imperialUnits) + + const mmFar = mmNear + mmDof + const mmHF = (-1 * mmDist * focalLength + mmDist * mmFar) / (-1 * mmDist + mmFar) + const coc = Math.pow(focalLength, 2) / (aperture * mmHF - aperture * focalLength) + const cropMultiplier = (100 * coc) / 3 + const cropFactor = Math.round((1 / cropMultiplier) * 1000) / 1000 + + return { cropFactor } +} diff --git a/module/src/types.d.ts b/module/src/types.d.ts index 722b15d5..32918a12 100644 --- a/module/src/types.d.ts +++ b/module/src/types.d.ts @@ -43,3 +43,7 @@ type ApertureResult = { aperture: number fStop: undefined | keyof typeof import('./utilities/aperture').preciseApertureMap } + +type CropFactorResult = { + cropFactor: number +} From c2e3adcc99172dbe8f2ec6e6577437eb048b866c Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Mon, 13 Feb 2023 08:52:25 +0100 Subject: [PATCH 13/17] consistent naming of 'near' prop --- module/src/calculators/calculateAperture.test.ts | 12 ++++++------ module/src/calculators/calculateAperture.ts | 6 +++--- module/src/calculators/calculateCropFactor.test.ts | 10 +++++----- module/src/calculators/calculateCropFactor.ts | 12 +++--------- module/src/calculators/calculateDepthOfField.ts | 6 ------ module/src/calculators/calculateFocalLength.test.ts | 12 ++++++------ module/src/calculators/calculateFocalLength.ts | 6 +++--- module/src/index.ts | 1 + 8 files changed, 27 insertions(+), 38 deletions(-) diff --git a/module/src/calculators/calculateAperture.test.ts b/module/src/calculators/calculateAperture.test.ts index b2c8661d..6fb47b56 100644 --- a/module/src/calculators/calculateAperture.test.ts +++ b/module/src/calculators/calculateAperture.test.ts @@ -8,7 +8,7 @@ describe('Calculating the depth of field with calculateAperture()', () => { cropFactor: 1, distance: 5, dof: 2.584690961719362, - nearLimit: 4.021931840567339, + near: 4.021931840567339, imperialUnits: false, }) @@ -21,7 +21,7 @@ describe('Calculating the depth of field with calculateAperture()', () => { cropFactor: 2, distance: 25, dof: 11.082093523926748, - nearLimit: 20.63203625607849, + near: 20.63203625607849, imperialUnits: false, }) @@ -35,7 +35,7 @@ describe('Calculating the depth of field with calculateAperture()', () => { cropFactor: 3.02, distance: 7, dof: 7.851429380291624, - nearLimit: 4.833680315786585, + near: 4.833680315786585, imperialUnits: false, }) @@ -48,7 +48,7 @@ describe('Calculating the depth of field with calculateAperture()', () => { cropFactor: 1, distance: 5, dof: Infinity, - nearLimit: 0.9715025906735751, + near: 0.9715025906735751, imperialUnits: false, }) @@ -63,7 +63,7 @@ describe('Calculating the depth of field with calculateAperture()', () => { cropFactor: 1, distance: 15, dof: 7.012923816256398, - nearLimit: 12.27274548830499, + near: 12.27274548830499, imperialUnits: true, }) @@ -76,7 +76,7 @@ describe('Calculating the depth of field with calculateAperture()', () => { cropFactor: 2.7, distance: 42, dof: 12.634717336600715, - nearLimit: 36.61227928000945, + near: 36.61227928000945, imperialUnits: true, }) diff --git a/module/src/calculators/calculateAperture.ts b/module/src/calculators/calculateAperture.ts index 44e9f173..a6fc6e13 100644 --- a/module/src/calculators/calculateAperture.ts +++ b/module/src/calculators/calculateAperture.ts @@ -9,19 +9,19 @@ export function calculateAperture({ cropFactor, distance, dof, - nearLimit, + near, imperialUnits, }: { focalLength: number cropFactor: number distance: number dof: number - nearLimit: number + near: number imperialUnits?: boolean }): ApertureResult { const mmDist = toMillimeters(distance, imperialUnits) const mmDof = toMillimeters(dof, imperialUnits) - const mmNear = toMillimeters(nearLimit, imperialUnits) + const mmNear = toMillimeters(near, imperialUnits) const mmFar = mmNear + mmDof const mmHF = (-1 * mmDist * focalLength + mmDist * mmFar) / (-1 * mmDist + mmFar) diff --git a/module/src/calculators/calculateCropFactor.test.ts b/module/src/calculators/calculateCropFactor.test.ts index c1574f41..cec74265 100644 --- a/module/src/calculators/calculateCropFactor.test.ts +++ b/module/src/calculators/calculateCropFactor.test.ts @@ -5,7 +5,7 @@ describe('Calculating the depth of field with calculateCropFactor()', () => { test('35mm, f/2, crop factor of 1, 5 meters', () => { const result = calculateCropFactor({ dof: 2.584690961719362, - nearLimit: 4.021931840567339, + near: 4.021931840567339, focalLength: 35, aperture: 2, distance: 5, @@ -18,7 +18,7 @@ describe('Calculating the depth of field with calculateCropFactor()', () => { test('50mm, f/1.4, crop factor of 2, 25 meters', () => { const result = calculateCropFactor({ dof: 11.082093523926748, - nearLimit: 20.63203625607849, + near: 20.63203625607849, focalLength: 50, aperture: 1.414214, distance: 25, @@ -34,7 +34,7 @@ describe('Calculating the depth of field with calculateCropFactor()', () => { focalLength: 28, aperture: 5.039684, dof: 7.851429380291624, - nearLimit: 4.833680315786585, + near: 4.833680315786585, distance: 7, imperialUnits: false, }) @@ -48,7 +48,7 @@ describe('Calculating the depth of field with calculateCropFactor()', () => { const result = calculateCropFactor({ focalLength: 35, aperture: 2, - nearLimit: 12.27274548830499, + near: 12.27274548830499, dof: 7.012923816256398, distance: 15, imperialUnits: true, @@ -62,7 +62,7 @@ describe('Calculating the depth of field with calculateCropFactor()', () => { focalLength: 55, aperture: 3.174802, dof: 12.634717336600715, - nearLimit: 36.61227928000945, + near: 36.61227928000945, distance: 42, imperialUnits: true, }) diff --git a/module/src/calculators/calculateCropFactor.ts b/module/src/calculators/calculateCropFactor.ts index 896bde1e..2594c6e4 100644 --- a/module/src/calculators/calculateCropFactor.ts +++ b/module/src/calculators/calculateCropFactor.ts @@ -2,22 +2,16 @@ import { toMillimeters } from '../utilities/units' /** * Returns the depth of field characteristics for a given lens' attributes - * - * @param focalLength - * @param aperture - * @param cropFactor - * @param distance - * @param imperialUnits */ export function calculateCropFactor({ - nearLimit, + near, dof, focalLength, aperture, distance, imperialUnits, }: { - nearLimit: number + near: number dof: number focalLength: number aperture: number @@ -26,7 +20,7 @@ export function calculateCropFactor({ }): CropFactorResult { const mmDist = toMillimeters(distance, imperialUnits) const mmDof = toMillimeters(dof, imperialUnits) - const mmNear = toMillimeters(nearLimit, imperialUnits) + const mmNear = toMillimeters(near, imperialUnits) const mmFar = mmNear + mmDof const mmHF = (-1 * mmDist * focalLength + mmDist * mmFar) / (-1 * mmDist + mmFar) diff --git a/module/src/calculators/calculateDepthOfField.ts b/module/src/calculators/calculateDepthOfField.ts index 4aa85411..80f8bbba 100644 --- a/module/src/calculators/calculateDepthOfField.ts +++ b/module/src/calculators/calculateDepthOfField.ts @@ -4,12 +4,6 @@ import { fromMillimeters, toMillimeters } from '../utilities/units' /** * Returns the depth of field characteristics for a given lens' attributes - * - * @param focalLength - * @param aperture - * @param cropFactor - * @param distance - * @param imperialUnits */ export function calculateDepthOfField({ focalLength, diff --git a/module/src/calculators/calculateFocalLength.test.ts b/module/src/calculators/calculateFocalLength.test.ts index e5e83a48..a4e36207 100644 --- a/module/src/calculators/calculateFocalLength.test.ts +++ b/module/src/calculators/calculateFocalLength.test.ts @@ -4,7 +4,7 @@ describe('Calculating the depth of field with calculateFocalLength()', () => { describe('metric units (meters)', () => { test('35mm, f/2, crop factor of 1, 5 meters', () => { const result = calculateFocalLength({ - nearLimit: 4.021931840567339, + near: 4.021931840567339, aperture: 2, cropFactor: 1, distance: 5, @@ -16,7 +16,7 @@ describe('Calculating the depth of field with calculateFocalLength()', () => { test('50mm, f/1.4, crop factor of 2, 25 meters', () => { const result = calculateFocalLength({ - nearLimit: 20.63203625607849, + near: 20.63203625607849, aperture: 1.414214, cropFactor: 2, distance: 25, @@ -29,7 +29,7 @@ describe('Calculating the depth of field with calculateFocalLength()', () => { test('28mm, f/5, crop factor of 3.02, 7 meters', () => { // Blackmagic Cine Cam sensor const result = calculateFocalLength({ - nearLimit: 4.833680315786585, + near: 4.833680315786585, aperture: 5.039684, cropFactor: 3.02, distance: 7, @@ -41,7 +41,7 @@ describe('Calculating the depth of field with calculateFocalLength()', () => { test('such that the far end of the range is infinity', () => { const result = calculateFocalLength({ - nearLimit: 0.9715025906735751, + near: 0.9715025906735751, aperture: 16, cropFactor: 1, distance: 5, @@ -55,7 +55,7 @@ describe('Calculating the depth of field with calculateFocalLength()', () => { describe('imperial units (feet)', () => { test('35mm, f/2, crop factor of 1, 15 feet', () => { const result = calculateFocalLength({ - nearLimit: 12.27274548830499, + near: 12.27274548830499, aperture: 2, cropFactor: 1, distance: 15, @@ -67,7 +67,7 @@ describe('Calculating the depth of field with calculateFocalLength()', () => { test('55mm, f/3.2, crop factor of 2.7, 42 feet', () => { const result = calculateFocalLength({ - nearLimit: 36.61227928000945, + near: 36.61227928000945, aperture: 3.174802, cropFactor: 2.7, distance: 42, diff --git a/module/src/calculators/calculateFocalLength.ts b/module/src/calculators/calculateFocalLength.ts index 8e83aefa..2a8dd1ee 100644 --- a/module/src/calculators/calculateFocalLength.ts +++ b/module/src/calculators/calculateFocalLength.ts @@ -5,13 +5,13 @@ import { toMillimeters } from '../utilities/units' * Returns the focal length for a given lens' attributes and depth of field */ export function calculateFocalLength({ - nearLimit, + near, aperture, cropFactor, distance, imperialUnits, }: { - nearLimit: number + near: number aperture: number cropFactor: number distance: number @@ -19,7 +19,7 @@ export function calculateFocalLength({ }): FocalLengthResult { // Convert to millimeters const mmDist = toMillimeters(distance, imperialUnits) - const mmNear = toMillimeters(nearLimit, imperialUnits) + const mmNear = toMillimeters(near, imperialUnits) const cropMultiplier = 1 / cropFactor const coc = Math.round(0.03 * cropMultiplier * 1000) / 1000 diff --git a/module/src/index.ts b/module/src/index.ts index 6d800b31..caa4b8be 100644 --- a/module/src/index.ts +++ b/module/src/index.ts @@ -7,3 +7,4 @@ export type { DepthOfFieldDetails } export { calculateDepthOfField } from './calculators/calculateDepthOfField' export { calculateAperture } from './calculators/calculateAperture' export { calculateFocalLength } from './calculators/calculateFocalLength' +export { calculateCropFactor } from './calculators/calculateCropFactor' From f9f91722222e3d748c9d5f88e3c07daa6a3369d4 Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 4 Mar 2023 12:28:49 +0100 Subject: [PATCH 14/17] tests for aperture mapping --- module/src/utilities/aperture.test.ts | 37 +++++- yarn.lock | 172 +++++++++++++------------- 2 files changed, 121 insertions(+), 88 deletions(-) diff --git a/module/src/utilities/aperture.test.ts b/module/src/utilities/aperture.test.ts index 373c5dcb..2cac1124 100644 --- a/module/src/utilities/aperture.test.ts +++ b/module/src/utilities/aperture.test.ts @@ -1,10 +1,11 @@ import { builtInDefaults } from '../Lens' -import { toActualAperture } from './aperture' +import { getApertureName, preciseApertureMap, toActualAperture } from './aperture' +import { objectKeysArray } from './objectKeysArray' const defaultOptionsAperture = builtInDefaults.aperture const defaultOptionsApertureNumber = Number(builtInDefaults.aperture.replace('f/', '')) -const customSettingsApertures = [undefined /* , 2.4, 'f/3.4' */] +const customSettingsApertures = [undefined, 2.4, 'f/3.4'] describe.each(customSettingsApertures)('toActualAperture', (customSettingsAperture) => { describe(`customSettingsAperture: ${customSettingsAperture}`, () => { @@ -63,3 +64,35 @@ describe.each(customSettingsApertures)('toActualAperture', (customSettingsApertu }) }) }) + +describe('getApertureName', () => { + describe.each(objectKeysArray(preciseApertureMap))('Verify every value in the mapping', (fstop) => { + test(`${preciseApertureMap[fstop]} -> ${fstop}`, () => { + expect(getApertureName(preciseApertureMap[fstop])).toBe(fstop) + }) + + test(`1% below the documented value still finds the applicable f-stop: ${ + preciseApertureMap[fstop] * 0.99 + } -> ${fstop}`, () => { + expect(getApertureName(preciseApertureMap[fstop] * 0.99)).toBe(fstop) + }) + + test(`1% above the documented value still finds the applicable f-stop: ${ + preciseApertureMap[fstop] * 1.01 + } -> ${fstop}`, () => { + expect(getApertureName(preciseApertureMap[fstop] * 1.01)).toBe(fstop) + }) + }) + + test(`Documented value 5.039684 results in the value it's mapped to, f/5`, () => { + expect(getApertureName(5.039684)).toBe('f/5') + }) + + test(`Undocumented value 5.01 results in the nearest aperture, f/5`, () => { + expect(getApertureName(5.01)).toBe('f/5') + }) + + test(`Undocumented value 4.99 results in the nearest aperture, f/5`, () => { + expect(getApertureName(4.99)).toBe('f/5') + }) +}) diff --git a/yarn.lock b/yarn.lock index 45e44c5d..a655e098 100644 --- a/yarn.lock +++ b/yarn.lock @@ -923,10 +923,10 @@ prop-types "^15.8.1" react-is "^18.2.0" -"@next/env@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/env/-/env-13.2.1.tgz#082d42cfc0c794e9185d7b4133d71440ba2e795d" - integrity sha512-Hq+6QZ6kgmloCg8Kgrix+4F0HtvLqVK3FZAnlAoS0eonaDemHe1Km4kwjSWRE3JNpJNcKxFHF+jsZrYo0SxWoQ== +"@next/env@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/env/-/env-13.2.3.tgz#77ca49edb3c1d7c5263bb8f2ebe686080e98279e" + integrity sha512-FN50r/E+b8wuqyRjmGaqvqNDuWBWYWQiigfZ50KnSFH0f+AMQQyaZl+Zm2+CIpKk0fL9QxhLxOpTVA3xFHgFow== "@next/eslint-plugin-next@13.1.6": version "13.1.6" @@ -942,70 +942,70 @@ dependencies: source-map "^0.7.0" -"@next/swc-android-arm-eabi@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.2.1.tgz#67f2580fbbe05ee006220688972c5e3a555fc741" - integrity sha512-Yua7mUpEd1wzIT6Jjl3dpRizIfGp9NR4F2xeRuQv+ae+SDI1Em2WyM9m46UL+oeW5GpMiEHoaBagr47RScZFmQ== - -"@next/swc-android-arm64@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.2.1.tgz#460a02b69eb23bb5f402266bcea9cadae59415c1" - integrity sha512-Bifcr2f6VwInOdq1uH/9lp8fH7Nf7XGkIx4XceVd32LPJqG2c6FZU8ZRBvTdhxzXVpt5TPtuXhOP4Ij9UPqsVw== - -"@next/swc-darwin-arm64@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.2.1.tgz#8b8530ff417802027471aee2419f78a58a863ccb" - integrity sha512-gvqm+fGMYxAkwBapH0Vvng5yrb6HTkIvZfY4oEdwwYrwuLdkjqnJygCMgpNqIFmAHSXgtlWxfYv1VC8sjN81Kw== - -"@next/swc-darwin-x64@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.2.1.tgz#80aebb3329a1e4568a28de1ee177780b3d50330c" - integrity sha512-HGqVqmaZWj6zomqOZUVbO5NhlABL0iIaxTmd0O5B0MoMa5zpDGoaHSG+fxgcWMXcGcxmUNchv1NfNOYiTKoHOg== - -"@next/swc-freebsd-x64@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.2.1.tgz#250ea2ab7e1734f22d11c677c463fab9ac33a516" - integrity sha512-N/a4JarAq+E+g+9K2ywJUmDIgU2xs2nA+BBldH0oq4zYJMRiUhL0iaN9G4e72VmGOJ61L/3W6VN8RIUOwTLoqQ== - -"@next/swc-linux-arm-gnueabihf@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.2.1.tgz#fe6bb29ed348a5f8ecae3740df22a8d8130c474a" - integrity sha512-WaFoerF/eRbhbE57TaIGJXbQAERADZ/RZ45u6qox9beb5xnWsyYgzX+WuN7Tkhyvga0/aMuVYFzS9CEay7D+bw== - -"@next/swc-linux-arm64-gnu@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.2.1.tgz#4781b927fc5e421f3cea2b29e5d38e5e4837b198" - integrity sha512-R+Jhc1/RJTnncE9fkePboHDNOCm1WJ8daanWbjKhfPySMyeniKYRwGn5SLYW3S8YlRS0QVdZaaszDSZWgUcsmA== - -"@next/swc-linux-arm64-musl@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.2.1.tgz#c2ba0a121b0255ba62450916bc70e6d0e26cbc98" - integrity sha512-oI1UfZPidGAVddlL2eOTmfsuKV9EaT1aktIzVIxIAgxzQSdwsV371gU3G55ggkurzfdlgF3GThFePDWF0d8dmw== - -"@next/swc-linux-x64-gnu@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.2.1.tgz#573c220f8b087e5d131d1fba58d3e1a670b220ad" - integrity sha512-PCygPwrQmS+7WUuAWWioWMZCzZm4PG91lfRxToLDg7yIm/3YfAw5N2EK2TaM9pzlWdvHQAqRMX/oLvv027xUiA== - -"@next/swc-linux-x64-musl@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.2.1.tgz#950b5bb920b322ca7b447efbd12a9c7a10c3a642" - integrity sha512-sUAKxo7CFZYGHNxheGh9nIBElLYBM6md/liEGfOTwh/xna4/GTTcmkGWkF7PdnvaYNgcPIQgHIMYiAa6yBKAVw== - -"@next/swc-win32-arm64-msvc@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.2.1.tgz#dbff3c4f5a3812a7059dac05804148a0f98682db" - integrity sha512-qDmyEjDBpl/vBXxuOOKKWmPQOcARcZIMach1s7kjzaien0SySut/PHRlj56sosa81Wt4hTGhfhZ1R7g1n7+B8w== - -"@next/swc-win32-ia32-msvc@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.2.1.tgz#7d2c17be7b8d9963984f5c15cc2588127101f620" - integrity sha512-2joqFQ81ZYPg6DcikIzQn3DgjKglNhPAozx6dL5sCNkr1CPMD0YIkJgT3CnYyMHQ04Qi3Npv0XX3MD6LJO8OCA== - -"@next/swc-win32-x64-msvc@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.2.1.tgz#09713c6a925461f414e89422851326d1625bd4d2" - integrity sha512-r3+0fSaIZT6N237iMzwUhfNwjhAFvXjqB+4iuW+wcpxW+LHm1g/IoxN8eSRcb8jPItC86JxjAxpke0QL97qd6g== +"@next/swc-android-arm-eabi@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.2.3.tgz#85eed560c87c7996558c868a117be9780778f192" + integrity sha512-mykdVaAXX/gm+eFO2kPeVjnOCKwanJ9mV2U0lsUGLrEdMUifPUjiXKc6qFAIs08PvmTMOLMNnUxqhGsJlWGKSw== + +"@next/swc-android-arm64@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.2.3.tgz#8ac54ca9795a48afc4631b4823a4864bd5db0129" + integrity sha512-8XwHPpA12gdIFtope+n9xCtJZM3U4gH4vVTpUwJ2w1kfxFmCpwQ4xmeGSkR67uOg80yRMuF0h9V1ueo05sws5w== + +"@next/swc-darwin-arm64@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.2.3.tgz#f674e3c65aec505b6d218a662ade3fe248ccdbda" + integrity sha512-TXOubiFdLpMfMtaRu1K5d1I9ipKbW5iS2BNbu8zJhoqrhk3Kp7aRKTxqFfWrbliAHhWVE/3fQZUYZOWSXVQi1w== + +"@next/swc-darwin-x64@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.2.3.tgz#a15ea7fb4c46034a8f5e387906d0cad08387075a" + integrity sha512-GZctkN6bJbpjlFiS5pylgB2pifHvgkqLAPumJzxnxkf7kqNm6rOGuNjsROvOWVWXmKhrzQkREO/WPS2aWsr/yw== + +"@next/swc-freebsd-x64@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.2.3.tgz#f7ac6ae4f7d706ff2431f33e40230a554c8c2cbc" + integrity sha512-rK6GpmMt/mU6MPuav0/M7hJ/3t8HbKPCELw/Uqhi4732xoq2hJ2zbo2FkYs56y6w0KiXrIp4IOwNB9K8L/q62g== + +"@next/swc-linux-arm-gnueabihf@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.2.3.tgz#84ad9e9679d55542a23b590ad9f2e1e9b2df62f7" + integrity sha512-yeiCp/Odt1UJ4KUE89XkeaaboIDiVFqKP4esvoLKGJ0fcqJXMofj4ad3tuQxAMs3F+qqrz9MclqhAHkex1aPZA== + +"@next/swc-linux-arm64-gnu@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.2.3.tgz#56f9175bc632d647c60b9e8bedc0875edf92d8b7" + integrity sha512-/miIopDOUsuNlvjBjTipvoyjjaxgkOuvlz+cIbbPcm1eFvzX2ltSfgMgty15GuOiR8Hub4FeTSiq3g2dmCkzGA== + +"@next/swc-linux-arm64-musl@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.2.3.tgz#7d4cf00e8f1729a3de464da0624773f5d0d14888" + integrity sha512-sujxFDhMMDjqhruup8LLGV/y+nCPi6nm5DlFoThMJFvaaKr/imhkXuk8uCTq4YJDbtRxnjydFv2y8laBSJVC2g== + +"@next/swc-linux-x64-gnu@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.2.3.tgz#17de404910c4ebf7a1d366b19334d7e27e126ab0" + integrity sha512-w5MyxPknVvC9LVnMenAYMXMx4KxPwXuJRMQFvY71uXg68n7cvcas85U5zkdrbmuZ+JvsO5SIG8k36/6X3nUhmQ== + +"@next/swc-linux-x64-musl@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.2.3.tgz#07cb7b7f3a3a98034e2533f82638a9b099ba4ab1" + integrity sha512-CTeelh8OzSOVqpzMFMFnVRJIFAFQoTsI9RmVJWW/92S4xfECGcOzgsX37CZ8K982WHRzKU7exeh7vYdG/Eh4CA== + +"@next/swc-win32-arm64-msvc@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.2.3.tgz#b9ac98c954c71ec9de45d3497a8585096b873152" + integrity sha512-7N1KBQP5mo4xf52cFCHgMjzbc9jizIlkTepe9tMa2WFvEIlKDfdt38QYcr9mbtny17yuaIw02FXOVEytGzqdOQ== + +"@next/swc-win32-ia32-msvc@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.2.3.tgz#5ec48653a48fd664e940c69c96bba698fdae92eb" + integrity sha512-LzWD5pTSipUXTEMRjtxES/NBYktuZdo7xExJqGDMnZU8WOI+v9mQzsmQgZS/q02eIv78JOCSemqVVKZBGCgUvA== + +"@next/swc-win32-x64-msvc@13.2.3": + version "13.2.3" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.2.3.tgz#cd432f280beb8d8de5b7cd2501e9f502e9f3dd72" + integrity sha512-aLG2MaFs4y7IwaMTosz2r4mVbqRyCnMoFqOcmfTi7/mAS+G4IMH0vJp4oLdbshqiVoiVuKrAfqtXj55/m7Qu1Q== "@nivo/annotations@0.80.0": version "0.80.0" @@ -5075,30 +5075,30 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next@13.2.1: - version "13.2.1" - resolved "https://registry.yarnpkg.com/next/-/next-13.2.1.tgz#34d823f518632b36379863228ed9f861c335b9c0" - integrity sha512-qhgJlDtG0xidNViJUPeQHLGJJoT4zDj/El7fP3D3OzpxJDUfxsm16cK4WTMyvSX1ciIfAq05u+0HqFAa+VJ+Hg== +next@13.2.3: + version "13.2.3" + resolved "https://registry.yarnpkg.com/next/-/next-13.2.3.tgz#92d170e7aca421321f230ff80c35c4751035f42e" + integrity sha512-nKFJC6upCPN7DWRx4+0S/1PIOT7vNlCT157w9AzbXEgKy6zkiPKEt5YyRUsRZkmpEqBVrGgOqNfwecTociyg+w== dependencies: - "@next/env" "13.2.1" + "@next/env" "13.2.3" "@swc/helpers" "0.4.14" caniuse-lite "^1.0.30001406" postcss "8.4.14" styled-jsx "5.1.1" optionalDependencies: - "@next/swc-android-arm-eabi" "13.2.1" - "@next/swc-android-arm64" "13.2.1" - "@next/swc-darwin-arm64" "13.2.1" - "@next/swc-darwin-x64" "13.2.1" - "@next/swc-freebsd-x64" "13.2.1" - "@next/swc-linux-arm-gnueabihf" "13.2.1" - "@next/swc-linux-arm64-gnu" "13.2.1" - "@next/swc-linux-arm64-musl" "13.2.1" - "@next/swc-linux-x64-gnu" "13.2.1" - "@next/swc-linux-x64-musl" "13.2.1" - "@next/swc-win32-arm64-msvc" "13.2.1" - "@next/swc-win32-ia32-msvc" "13.2.1" - "@next/swc-win32-x64-msvc" "13.2.1" + "@next/swc-android-arm-eabi" "13.2.3" + "@next/swc-android-arm64" "13.2.3" + "@next/swc-darwin-arm64" "13.2.3" + "@next/swc-darwin-x64" "13.2.3" + "@next/swc-freebsd-x64" "13.2.3" + "@next/swc-linux-arm-gnueabihf" "13.2.3" + "@next/swc-linux-arm64-gnu" "13.2.3" + "@next/swc-linux-arm64-musl" "13.2.3" + "@next/swc-linux-x64-gnu" "13.2.3" + "@next/swc-linux-x64-musl" "13.2.3" + "@next/swc-win32-arm64-msvc" "13.2.3" + "@next/swc-win32-ia32-msvc" "13.2.3" + "@next/swc-win32-x64-msvc" "13.2.3" node-int64@^0.4.0: version "0.4.0" From 1ec6af7339c316b32354cbe246834802e7ce2f3f Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 4 Mar 2023 12:33:22 +0100 Subject: [PATCH 15/17] more tests for aperture mapping --- module/src/data/preciseApertureMap.ts | 46 +++++++++++++++++++++++++ module/src/index.ts | 3 +- module/src/utilities/aperture.test.ts | 3 +- module/src/utilities/aperture.ts | 48 ++------------------------- 4 files changed, 52 insertions(+), 48 deletions(-) create mode 100644 module/src/data/preciseApertureMap.ts diff --git a/module/src/data/preciseApertureMap.ts b/module/src/data/preciseApertureMap.ts new file mode 100644 index 00000000..5067fd67 --- /dev/null +++ b/module/src/data/preciseApertureMap.ts @@ -0,0 +1,46 @@ +/** + * Map of human-friendly f-stop values to their precise numeric values + */ +export const preciseApertureMap: Record = { + 'f/1': 1, + 'f/1.2': 1.189207, + 'f/1.4': 1.414214, + 'f/1.6': 1.587401, + 'f/1.7': 1.681793, + 'f/1.8': 1.781797, + 'f/2': 2.0, + 'f/2.2': 2.244924, + 'f/2.4': 2.378414, + 'f/2.5': 2.519842, + 'f/2.8': 2.828427, + 'f/3.2': 3.174802, + 'f/3.4': 3.363586, + 'f/3.6': 3.563595, + 'f/4': 4.0, + 'f/4.5': 4.489848, + 'f/4.8': 4.756828, + 'f/5': 5.039684, + 'f/5.6': 5.656854, + 'f/6.4': 6.349604, + 'f/6.7': 6.727171, + 'f/7.1': 7.12719, + 'f/8': 8.0, + 'f/9': 8.979696, + 'f/9.5': 9.513657, + 'f/10': 10.07937, + 'f/11': 11.313708, + 'f/12.7': 12.699208, + 'f/13.5': 13.454343, + 'f/14.3': 14.254379, + 'f/16': 16.0, + 'f/18': 17.959393, + 'f/19': 19.027314, + 'f/20': 20.158737, + 'f/22': 22.627417, + 'f/25': 25.398417, + 'f/27': 26.908685, + 'f/28': 28.508759, + 'f/32': 32, + 'f/45': 45.254834, + 'f/64': 64, +} diff --git a/module/src/index.ts b/module/src/index.ts index caa4b8be..05d68468 100644 --- a/module/src/index.ts +++ b/module/src/index.ts @@ -1,6 +1,7 @@ export { Lens } from './Lens' export { createLensMaker } from './createLensMaker' -export { preciseApertureMap as apertureMap, getApertureName, isApertureString } from './utilities/aperture' +export { getApertureName, isApertureString } from './utilities/aperture' +export { preciseApertureMap as apertureMap } from './data/preciseApertureMap' type DepthOfFieldDetails = DoFResult export type { DepthOfFieldDetails } diff --git a/module/src/utilities/aperture.test.ts b/module/src/utilities/aperture.test.ts index 2cac1124..c0e7d819 100644 --- a/module/src/utilities/aperture.test.ts +++ b/module/src/utilities/aperture.test.ts @@ -1,5 +1,6 @@ import { builtInDefaults } from '../Lens' -import { getApertureName, preciseApertureMap, toActualAperture } from './aperture' +import { getApertureName, toActualAperture } from './aperture' +import { preciseApertureMap } from '../data/preciseApertureMap' import { objectKeysArray } from './objectKeysArray' const defaultOptionsAperture = builtInDefaults.aperture diff --git a/module/src/utilities/aperture.ts b/module/src/utilities/aperture.ts index a590ad76..deb36915 100644 --- a/module/src/utilities/aperture.ts +++ b/module/src/utilities/aperture.ts @@ -1,52 +1,8 @@ +import { preciseApertureMap } from '../data/preciseApertureMap' import { objectKeysArray } from './objectKeysArray' const apertureRegex = /^f\/(\d+(?:\.\d+)?)$/ -// Map of human-friendly values to their precise numeric values -export const preciseApertureMap: Record = { - 'f/1': 1, - 'f/1.2': 1.189207, - 'f/1.4': 1.414214, - 'f/1.6': 1.587401, - 'f/1.7': 1.681793, - 'f/1.8': 1.781797, - 'f/2': 2.0, - 'f/2.2': 2.244924, - 'f/2.4': 2.378414, - 'f/2.5': 2.519842, - 'f/2.8': 2.828427, - 'f/3.2': 3.174802, - 'f/3.4': 3.363586, - 'f/3.6': 3.563595, - 'f/4': 4.0, - 'f/4.5': 4.489848, - 'f/4.8': 4.756828, - 'f/5': 5.039684, - 'f/5.6': 5.656854, - 'f/6.4': 6.349604, - 'f/6.7': 6.727171, - 'f/7.1': 7.12719, - 'f/8': 8.0, - 'f/9': 8.979696, - 'f/9.5': 9.513657, - 'f/10': 10.07937, - 'f/11': 11.313708, - 'f/12.7': 12.699208, - 'f/13.5': 13.454343, - 'f/14.3': 14.254379, - 'f/16': 16.0, - 'f/18': 17.959393, - 'f/19': 19.027314, - 'f/20': 20.158737, - 'f/22': 22.627417, - 'f/25': 25.398417, - 'f/27': 26.908685, - 'f/28': 28.508759, - 'f/32': 32, - 'f/45': 45.254834, - 'f/64': 64, -} - // It's possible that lenses might excede what we have listed in this map, so let's give the benefit of the doubt and accept those numbers as-is. To do this, we need to know the smallest and largest values in our map. // We need to ignore test coverage for this line, otherwise it is marked as uncovered; this happens because we're ignoring the thrown exception near the end /* istanbul ignore next line */ @@ -58,7 +14,7 @@ const largestDocumentedAperture = sortedValues.slice(-1)[0] * Takes a human-friendly string and returns a precise numeric value that is equivalent * @example 'f/5' => 5.039684 */ -function getPreciseAperture(humanValue: string): number | undefined { +function getPreciseAperture(humanValue: ApertureString): number | undefined { if ( humanValue in preciseApertureMap && Object.prototype.hasOwnProperty.call(preciseApertureMap, humanValue) && From 0f46864e2846b08459c9bdfee8626c9164d3947a Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sat, 4 Mar 2023 13:04:29 +0100 Subject: [PATCH 16/17] fix type import --- module/src/types.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/src/types.d.ts b/module/src/types.d.ts index 32918a12..0946175b 100644 --- a/module/src/types.d.ts +++ b/module/src/types.d.ts @@ -41,7 +41,7 @@ type FocalLengthResult = { type ApertureResult = { aperture: number - fStop: undefined | keyof typeof import('./utilities/aperture').preciseApertureMap + fStop: undefined | keyof typeof import('./data/preciseApertureMap').preciseApertureMap } type CropFactorResult = { From ee254d12b931f18190a611632c5a90a013387dc3 Mon Sep 17 00:00:00 2001 From: Craig Patik Date: Sun, 7 Dec 2025 20:57:24 +0100 Subject: [PATCH 17/17] post-merge fixes --- app/src/ui/Graph/useData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/ui/Graph/useData.ts b/app/src/ui/Graph/useData.ts index b54b3237..3418775d 100644 --- a/app/src/ui/Graph/useData.ts +++ b/app/src/ui/Graph/useData.ts @@ -1,11 +1,11 @@ import { LineSeries } from '@nivo/line' import { compact } from 'lodash' import { useMemo } from 'react' +import { Lens } from '../../../../package/dist/Lens' import useDoFStore from '../../store' import sensorList from '../../utilities/sensorList' import useIsMobile from '../../utilities/useIsMobile' import getDistanceSteps from './getDistanceSteps' -import { Lens } from 'dof' import getUniqueLensNames from './getUniqueLensNames' export default function useData() {