@jjlmoya/utils-forensic-science 1.19.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/scripts/validate-icons.mjs +57 -0
- package/src/category/index.ts +10 -10
- package/src/entries.ts +26 -25
- package/src/index.ts +7 -6
- package/src/tests/locale_completeness.test.ts +23 -23
- package/src/tests/tool_validation.test.ts +16 -16
- package/src/tool/forensic-evidence-scale-calculator/bibliography.astro +9 -0
- package/src/tool/forensic-evidence-scale-calculator/bibliography.ts +16 -0
- package/src/tool/forensic-evidence-scale-calculator/component.astro +154 -0
- package/src/tool/forensic-evidence-scale-calculator/entry.ts +29 -0
- package/src/tool/forensic-evidence-scale-calculator/forensic-evidence-scale-calculator.css +516 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/de.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/en.ts +299 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/es.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/fr.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/id.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/it.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/ja.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/ko.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/localized-content.ts +1537 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/nl.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/pl.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/pt.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/ru.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/sv.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/tr.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/i18n/zh.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/index.ts +11 -0
- package/src/tool/forensic-evidence-scale-calculator/logic.test.ts +55 -0
- package/src/tool/forensic-evidence-scale-calculator/logic.ts +107 -0
- package/src/tool/forensic-evidence-scale-calculator/seo.astro +10 -0
- package/src/tool/forensic-evidence-scale-calculator/ui.ts +3 -0
- package/src/tool/forensic-evidence-scale-calculator/unit-selector.ts +120 -0
- package/src/tool/forensic-evidence-scale-calculator/view.ts +203 -0
- package/src/tools.ts +8 -6
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { bibliography } from "../bibliography";
|
|
2
|
+
import type { ToolLocaleContent } from "../../../types";
|
|
3
|
+
import type { ForensicEvidenceScaleUI } from "../ui";
|
|
4
|
+
|
|
5
|
+
const slug = "forensic-evidence-scale-calculator";
|
|
6
|
+
const title = "Forensic Evidence Scale Calculator";
|
|
7
|
+
const description =
|
|
8
|
+
"Convert a measured length in a scaled evidence photograph into a traceable real-world estimate with an uncertainty range and perspective warning.";
|
|
9
|
+
|
|
10
|
+
const ui: ForensicEvidenceScaleUI = {
|
|
11
|
+
sceneAria:
|
|
12
|
+
"Illustration of a photographed evidence fragment, a reference scale, and two measurement lines.",
|
|
13
|
+
sceneKicker: "Calibration view",
|
|
14
|
+
sceneTitle: "Pixels become a documented length",
|
|
15
|
+
sceneNote:
|
|
16
|
+
"The reference and evidence measurements must describe the same image plane.",
|
|
17
|
+
evidenceLength: "Evidence length",
|
|
18
|
+
referenceLength: "Reference length",
|
|
19
|
+
controls: "Measurement inputs",
|
|
20
|
+
controlKicker: "Enter the two pixel measurements",
|
|
21
|
+
controlHelper:
|
|
22
|
+
"Use a visible ruler, scale, or object with a known real size in the same photograph.",
|
|
23
|
+
referenceRealSize: "Known reference size",
|
|
24
|
+
referenceRealHelp: "The real length printed on the scale or object.",
|
|
25
|
+
referencePixelLength: "Reference length in pixels",
|
|
26
|
+
evidencePixelLength: "Evidence length in pixels",
|
|
27
|
+
pixelHelp: "Measure both endpoints in the image.",
|
|
28
|
+
uncertaintyPercent: "Measurement margin (%)",
|
|
29
|
+
uncertaintyHelp: "A transparent margin for reading and calibration error.",
|
|
30
|
+
unit: "Real-world unit",
|
|
31
|
+
millimetres: "Millimetres (mm)",
|
|
32
|
+
centimetres: "Centimetres (cm)",
|
|
33
|
+
inches: "Inches (in)",
|
|
34
|
+
samePlane: "Reference and evidence are on the same plane",
|
|
35
|
+
samePlaneHelp:
|
|
36
|
+
"Keep this checked when both lengths lie on the same flat surface.",
|
|
37
|
+
disclaimer:
|
|
38
|
+
"Educational measurement aid. It does not correct perspective, establish chain of custody, or replace validated forensic photography and expert review.",
|
|
39
|
+
results: "Calculated evidence measurement",
|
|
40
|
+
resultKicker: "Documentable estimate",
|
|
41
|
+
calculatedMessage:
|
|
42
|
+
"The estimate is scaled from the reference length you entered.",
|
|
43
|
+
notCalculated: "Not calculated",
|
|
44
|
+
enterValues: "Enter positive measurements to calculate the estimate.",
|
|
45
|
+
interval: "Estimated interval",
|
|
46
|
+
scaleFactor: "Scale factor",
|
|
47
|
+
margin: "Applied margin",
|
|
48
|
+
traceLabel: "Calculation trace",
|
|
49
|
+
formulaPending: "The calculation trace will appear here.",
|
|
50
|
+
samePlaneMessage:
|
|
51
|
+
"Same-plane check is active. Review the photograph for alignment, focus, and endpoint placement.",
|
|
52
|
+
perspectiveWarning:
|
|
53
|
+
"Perspective warning: a flat scale and the evidence are not marked as coplanar. Treat this result as a rough estimate until geometry is corrected or the image is replaced.",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const faq = [
|
|
57
|
+
{
|
|
58
|
+
question: "What does this forensic evidence scale calculator do?",
|
|
59
|
+
answer:
|
|
60
|
+
"It uses a known real-world reference length and two pixel measurements from one photograph to estimate the evidence length. It also applies the margin you enter to show an interval instead of presenting a false exact value.",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
question: "What is the scale formula?",
|
|
64
|
+
answer:
|
|
65
|
+
"The scale factor is known reference size divided by reference pixels. Estimated evidence size is evidence pixels multiplied by that factor. The interval expands the estimate by the entered percentage margin.",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
question: "Why must the reference and evidence be on the same plane?",
|
|
69
|
+
answer:
|
|
70
|
+
"An oblique camera angle can make distances at different depths appear at different scales. A ruler beside an elevated or recessed object may therefore produce a biased result even when the arithmetic is correct.",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
question: "Can this replace a forensic report or identify evidence?",
|
|
74
|
+
answer:
|
|
75
|
+
"No. It does not identify evidence, correct perspective, validate a camera setup, preserve the original file, or establish chain of custody. Use it as a transparent arithmetic check and document the image, reference, method, assumptions, and review separately.",
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
const howTo = [
|
|
80
|
+
{
|
|
81
|
+
name: "Read the reference scale",
|
|
82
|
+
text: "Enter the known real size of the ruler interval or object visible in the photograph and choose its unit.",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "Measure both lengths in pixels",
|
|
86
|
+
text: "Measure the reference interval and the evidence interval using the same image and the same endpoint convention.",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "Add a realistic margin",
|
|
90
|
+
text: "Include a percentage for endpoint reading, image resolution, and calibration uncertainty. Do not use the margin to hide perspective problems.",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "Record the interval and trace",
|
|
94
|
+
text: "Use the estimate, interval, scale factor, and calculation trace as a compact note alongside the original photograph and your methodological limitations.",
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
export const content: ToolLocaleContent<ForensicEvidenceScaleUI> = {
|
|
99
|
+
slug,
|
|
100
|
+
title,
|
|
101
|
+
description,
|
|
102
|
+
ui,
|
|
103
|
+
seo: [
|
|
104
|
+
{
|
|
105
|
+
type: "title",
|
|
106
|
+
text: "How to Measure Evidence from a Scaled Photograph",
|
|
107
|
+
level: 2,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: "paragraph",
|
|
111
|
+
html: "This calculator turns a known reference length and two pixel spans into a <strong>real-world estimate with an explicit interval</strong>. It is designed for a quick, documented arithmetic check when a technician or student is reviewing one photograph.",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: "paragraph",
|
|
115
|
+
html: "The reference is the anchor for the calculation. It may be a marked ruler interval or another object whose real length is known before the image is measured. Enter that real length in millimetres, centimetres, or inches, then measure the same interval in pixels.",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: "paragraph",
|
|
119
|
+
html: "The evidence span is measured in the same image space. Use the same zoom context and endpoint rule for both spans, because changing how an edge is selected can change the result. The displayed formula keeps those inputs visible for a second reader.",
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: "paragraph",
|
|
123
|
+
html: "The percentage margin is a sensitivity allowance for reading and calibration uncertainty. It expands the estimate into a lower and upper bound; it is not a laboratory uncertainty budget, a confidence interval, or proof that the photograph is metrically calibrated.",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: "paragraph",
|
|
127
|
+
html: "Coplanarity is the central geometric assumption. A ruler and an item at different depths can have different image scales, especially when the camera is oblique. If that condition is plausible, keep the warning visible and replace the arithmetic check with a validated imaging procedure.",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: "paragraph",
|
|
131
|
+
html: "Use the result as a compact note beside the original file, not as a substitute for evidence handling. Record the source image identity, the reference interval, both pixel spans, the unit, the margin, and any perspective, focus, distortion, or processing limitation that could affect interpretation.",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: "stats",
|
|
135
|
+
items: [
|
|
136
|
+
{
|
|
137
|
+
value: "2",
|
|
138
|
+
label: "pixel spans to compare",
|
|
139
|
+
icon: "mdi:vector-line",
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
value: "1",
|
|
143
|
+
label: "transparent scale ratio",
|
|
144
|
+
icon: "mdi:calculator-variant-outline",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
value: "±",
|
|
148
|
+
label: "reading margin shown",
|
|
149
|
+
icon: "mdi:arrow-expand-horizontal",
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
columns: 3,
|
|
153
|
+
},
|
|
154
|
+
{ type: "title", text: "The scale ratio", level: 3 },
|
|
155
|
+
{
|
|
156
|
+
type: "code",
|
|
157
|
+
code: "evidence size = evidence pixels × (reference size ÷ reference pixels)",
|
|
158
|
+
ariaLabel: "Forensic evidence scale formula",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: "card",
|
|
162
|
+
icon: "mdi:ruler-square",
|
|
163
|
+
title: "Before you measure",
|
|
164
|
+
html: "Choose a visible ruler interval or object with a known real size. Measure both endpoints in the same image, keep the unit consistent, and note the image zoom and endpoint convention. The calculator reports arithmetic; it does not repair a photograph.",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: "table",
|
|
168
|
+
headers: ["Step", "Input", "Output"],
|
|
169
|
+
rows: [
|
|
170
|
+
[
|
|
171
|
+
"Reference ratio",
|
|
172
|
+
"reference size ÷ reference pixels",
|
|
173
|
+
"real-world units per pixel",
|
|
174
|
+
],
|
|
175
|
+
[
|
|
176
|
+
"Evidence estimate",
|
|
177
|
+
"evidence pixels × ratio",
|
|
178
|
+
"estimated evidence length",
|
|
179
|
+
],
|
|
180
|
+
[
|
|
181
|
+
"Reading interval",
|
|
182
|
+
"estimate ± entered margin",
|
|
183
|
+
"lower and upper sensitivity bounds",
|
|
184
|
+
],
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
{ type: "title", text: "When the estimate is useful", level: 3 },
|
|
188
|
+
{
|
|
189
|
+
type: "comparative",
|
|
190
|
+
columns: 2,
|
|
191
|
+
items: [
|
|
192
|
+
{
|
|
193
|
+
title: "Good fit for a quick check",
|
|
194
|
+
description:
|
|
195
|
+
"Use the calculator when the scale and the evidence are photographed on the same flat plane and you need a reproducible note.",
|
|
196
|
+
points: [
|
|
197
|
+
"Known reference interval",
|
|
198
|
+
"Same image plane",
|
|
199
|
+
"Explicit reading margin",
|
|
200
|
+
],
|
|
201
|
+
highlight: true,
|
|
202
|
+
pointIcon: "mdi:check",
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
title: "Stop and validate the geometry",
|
|
206
|
+
description:
|
|
207
|
+
"Do not treat a ruler as a universal perspective correction when depth, angle, distortion, or scale placement can change the ratio.",
|
|
208
|
+
points: [
|
|
209
|
+
"Different depths",
|
|
210
|
+
"Oblique camera angle",
|
|
211
|
+
"Material distortion or blur",
|
|
212
|
+
],
|
|
213
|
+
pointIcon: "mdi:alert-outline",
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
},
|
|
217
|
+
{ type: "title", text: "Working vocabulary", level: 3 },
|
|
218
|
+
{
|
|
219
|
+
type: "glossary",
|
|
220
|
+
items: [
|
|
221
|
+
{
|
|
222
|
+
term: "Reference length",
|
|
223
|
+
definition:
|
|
224
|
+
"The known real-world span represented by the ruler interval or object in the photograph.",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
term: "Pixel length",
|
|
228
|
+
definition:
|
|
229
|
+
"The image-space distance between the two endpoints selected for a reference or evidence span.",
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
term: "Scale factor",
|
|
233
|
+
definition:
|
|
234
|
+
"The reference size divided by its pixel length. It expresses the selected real-world unit per image pixel.",
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
term: "Sensitivity interval",
|
|
238
|
+
definition:
|
|
239
|
+
"A simple range around the estimate created from the percentage margin entered by the user. It is not a validated expanded uncertainty.",
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
type: "summary",
|
|
245
|
+
title: "A traceable note should include",
|
|
246
|
+
items: [
|
|
247
|
+
"The source image and file identity.",
|
|
248
|
+
"The reference interval, evidence interval, unit, and endpoint rule.",
|
|
249
|
+
"The displayed estimate, interval, scale factor, and chosen margin.",
|
|
250
|
+
"A clear statement about plane alignment and any perspective limitation.",
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
type: "diagnostic",
|
|
255
|
+
variant: "warning",
|
|
256
|
+
title: "Perspective is a geometry problem",
|
|
257
|
+
badge: "LIMIT",
|
|
258
|
+
icon: "mdi:camera-off-outline",
|
|
259
|
+
html: "If the reference and evidence sit at different depths, the same pixel-to-length ratio may not apply to both. This tool flags the condition but does not perform projective correction, authenticate the file, or establish chain of custody.",
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
type: "tip",
|
|
263
|
+
title: "Use this as a transparent arithmetic check",
|
|
264
|
+
html: "The result is an estimate for documentation and review, not a forensic conclusion. Preserve the original photograph and use a validated imaging method when geometry or evidentiary requirements are material.",
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
faq,
|
|
268
|
+
bibliography,
|
|
269
|
+
howTo,
|
|
270
|
+
schemas: [
|
|
271
|
+
{
|
|
272
|
+
"@context": "https://schema.org",
|
|
273
|
+
"@type": "SoftwareApplication",
|
|
274
|
+
name: title,
|
|
275
|
+
description,
|
|
276
|
+
applicationCategory: "EducationalApplication",
|
|
277
|
+
operatingSystem: "Any",
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"@context": "https://schema.org",
|
|
281
|
+
"@type": "FAQPage",
|
|
282
|
+
mainEntity: faq.map((item) => ({
|
|
283
|
+
"@type": "Question",
|
|
284
|
+
name: item.question,
|
|
285
|
+
acceptedAnswer: { "@type": "Answer", text: item.answer },
|
|
286
|
+
})),
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"@context": "https://schema.org",
|
|
290
|
+
"@type": "HowTo",
|
|
291
|
+
name: title,
|
|
292
|
+
step: howTo.map((step) => ({
|
|
293
|
+
"@type": "HowToStep",
|
|
294
|
+
name: step.name,
|
|
295
|
+
text: step.text,
|
|
296
|
+
})),
|
|
297
|
+
},
|
|
298
|
+
],
|
|
299
|
+
};
|