@johnmorrisdotca/dougu-sports 0.8.0 → 0.10.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/CHANGELOG.md +27 -0
- package/NOTICE.md +14 -0
- package/README.md +58 -26
- package/dist/brands/brand.ball.d.ts +29 -0
- package/dist/brands/brand.ball.js +23 -0
- package/dist/brands/brand.data.d.ts +47 -0
- package/dist/brands/brand.data.js +308 -0
- package/dist/brands/brand.letters.d.ts +31 -0
- package/dist/brands/brand.letters.js +88 -0
- package/dist/brands/brand.render.d.ts +47 -0
- package/dist/brands/brand.render.js +106 -0
- package/dist/brands-entry.d.ts +8 -0
- package/dist/brands-entry.js +5 -0
- package/dist/emblems/award/ribbon.d.ts +2 -0
- package/dist/emblems/award/ribbon.js +17 -0
- package/dist/emblems/ball/ball.baseball.js +2 -1
- package/dist/emblems/ball/ball.contrast.d.ts +4 -0
- package/dist/emblems/ball/ball.contrast.js +22 -0
- package/dist/emblems/ball/ball.core.d.ts +42 -0
- package/dist/emblems/ball/ball.core.js +34 -1
- package/dist/emblems/ball/ball.engine.d.ts +70 -4
- package/dist/emblems/ball/ball.engine.js +70 -20
- package/dist/emblems/ball/ball.family.seamed.d.ts +4 -0
- package/dist/emblems/ball/ball.family.seamed.js +42 -7
- package/dist/emblems/ball/ball.image.d.ts +8 -0
- package/dist/emblems/ball/ball.image.js +14 -5
- package/dist/emblems/ball/ball.index.js +2 -4
- package/dist/emblems/ball/ball.letters.d.ts +3 -0
- package/dist/emblems/ball/ball.letters.js +51 -0
- package/dist/emblems/ball/ball.print.d.ts +81 -0
- package/dist/emblems/ball/ball.print.js +268 -0
- package/dist/emblems/ball/ball.printable.d.ts +6 -0
- package/dist/emblems/ball/ball.printable.js +13 -0
- package/dist/emblems/ball/ball.region.d.ts +12 -0
- package/dist/emblems/ball/ball.region.js +94 -0
- package/dist/emblems/ball/ball.script.d.ts +15 -0
- package/dist/emblems/ball/ball.script.js +107 -0
- package/dist/emblems/ball/ball.soccer.js +7 -3
- package/dist/emblems/ball/ball.soccer.panels.d.ts +2 -0
- package/dist/emblems/ball/ball.soccer.panels.js +6 -3
- package/dist/emblems/ball/ball.soccer.size.d.ts +2 -0
- package/dist/emblems/ball/ball.soccer.size.js +8 -0
- package/dist/emblems/ball/ball.softball.js +2 -1
- package/dist/emblems/ball/ball.warp.d.ts +48 -0
- package/dist/emblems/ball/ball.warp.js +441 -0
- package/dist/emblems/emblem.core.d.ts +13 -0
- package/dist/emblems/emblem.equipment.js +3 -3
- package/dist/emblems/emblem.ids.d.ts +4 -4
- package/dist/emblems/emblem.ids.js +2 -2
- package/dist/emblems/emblem.registry.js +2 -0
- package/dist/emblems/gear/gear.index.js +2 -1
- package/dist/emblems/gear/gear.nets.d.ts +3 -0
- package/dist/emblems/gear/gear.nets.js +103 -0
- package/dist/emblems-entry.d.ts +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +5 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// An original cursive script, drawn for this package: a pen's centre line through hand-placed waypoints, joined letter to letter at the baseline, with the pen's thick down strokes and hairline up
|
|
2
|
+
// strokes made by the caller from each segment's direction (`tier`). No font file, no licensed outline and no maker's lettering: every waypoint below was placed by hand, in a grid where the x-height is 10,
|
|
3
|
+
// the ascender 20 and the descender -10, with y up. A glyph enters at (0, 0) and leaves at (adv, 0), so the next one starts where it stops. Imports nothing.
|
|
4
|
+
const LOWER = {
|
|
5
|
+
a: { adv: 8.4, d: "0,0 1.6,2.6 3.6,6.2 5.2,8.6 6.4,9.6 4.6,10.4 2.4,9.2 1.2,6 1.5,2.4 3.4,0.5 5.2,1.4 6.3,4.4 6.7,9.4 6.7,5 6.8,1.4 7.6,0.2 8.4,0" },
|
|
6
|
+
b: { adv: 8.6, d: "0,0 1.6,3.5 3.4,9 4.6,15.5 4.6,19.5 3.8,20.8 2.8,19.4 2.9,15 3.6,9 4,3.5 4.2,0.8 4.8,3.2 6.5,6.6 7.8,5.6 7.6,2.2 5.8,0.4 3.8,1.4 3.3,3.4 4.3,0.3 7.2,0 8.6,0" },
|
|
7
|
+
c: { adv: 7.4, d: "0,0 1.8,2.8 3.8,7 5.8,9.4 4.8,10.2 2.6,9 1.2,5.8 1.6,2.2 3.4,0.3 5.4,0.8 6.6,1.8 7.4,0" },
|
|
8
|
+
d: { adv: 9, d: "0,0 1.6,2.6 3.6,6.2 5.2,8.6 6.4,9.6 4.6,10.4 2.4,9.2 1.2,6 1.5,2.4 3.4,0.5 5.2,1.4 6.4,4.4 7.2,11 8,17.5 8,20.2 7.1,20.8 6.5,19.3 6.7,13 7,6 7.1,1.4 8,0.2 9,0" },
|
|
9
|
+
e: { adv: 7.6, d: "0,0 0.9,2.4 1.7,5 3.2,5.8 4.9,5.7 5.4,8.2 4.2,10.1 2.6,9.8 1.2,7.6 1.1,3.8 2.1,1.2 3.8,0.2 5.6,0.9 7,0.2 7.6,0" },
|
|
10
|
+
f: { adv: 6.4, d: "0,0 1.4,3.5 3.2,9.5 4.8,16.5 5.4,19.6 4.4,20.8 3.2,19 3.5,14 3.6,6 3.4,-2.4 2.2,-8.4 1,-9.6 0,-8 1,-5.2 3.6,-3 5.4,0.4 6.4,0 ; 0.6,10.2 4.4,10.8 7.2,10.2" },
|
|
11
|
+
g: { adv: 8.6, d: "0,0 1.6,2.6 3.6,6.2 5.2,8.6 6.4,9.6 4.6,10.4 2.4,9.2 1.2,6 1.5,2.4 3.4,0.5 5.2,1.4 6.4,4.4 6.8,9.6 6.4,3 6.2,-4.6 4.8,-9 2.4,-9.8 1,-8.2 2,-6.8 5,-6 7,-3.6 8,-0.5 8.6,0" },
|
|
12
|
+
h: { adv: 8.6, d: "0,0 1.6,3.5 3.4,9 4.6,15.5 4.6,19.5 3.8,20.8 2.8,19.4 2.9,15 3.6,9 4,3.5 4.1,0.4 4.6,3.6 6,7.8 7.2,8 7.5,5 7.1,1.4 7.6,0.2 8.6,0" },
|
|
13
|
+
i: { adv: 4.8, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.8,4.4 2.6,1 3.2,0.2 4.8,0 ; 3.2,12.8 3.2,13.4" },
|
|
14
|
+
j: { adv: 4.8, d: "0,0 1.4,3.4 2.4,8.2 3,9.6 3.2,3 3,-4.6 1.6,-9 0.2,-9.8 -0.8,-8.4 0.6,-6.8 2.6,-4 3.8,-0.5 4.8,0 ; 3.6,12.8 3.6,13.4" },
|
|
15
|
+
k: { adv: 8.2, d: "0,0 1.6,3.5 3.4,9 4.6,15.5 4.6,19.5 3.8,20.8 2.8,19.4 2.9,15 3.6,9 4,3.5 4.1,0.4 4.4,3.2 5,6.2 6.6,8 7,6.4 5.8,4.2 4.4,3.6 5.6,2.6 6.8,0.4 8.2,0" },
|
|
16
|
+
l: { adv: 4.8, d: "0,0 1.6,3.5 3.2,9.5 4.2,15.5 4.4,19.4 3.6,20.8 2.6,19.4 2.7,15 3.2,9 3.5,3.5 3.6,0.6 4.1,0.2 4.8,0" },
|
|
17
|
+
m: { adv: 12.8, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.9,5.5 2.8,1 3.2,3.6 4.4,8 5.6,8.4 6.1,5.2 6,1 6.4,3.6 7.6,8 8.8,8.4 9.4,5.2 9.2,1.2 9.9,0.2 10.8,0.6 12.8,0" },
|
|
18
|
+
n: { adv: 8.4, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.9,5.5 2.8,1 3.2,3.6 4.4,8 5.6,8.4 6.2,5.2 6,1.2 6.8,0.2 8.4,0" },
|
|
19
|
+
o: { adv: 7.6, d: "0,0 1.8,2.8 3.4,6.4 4.4,8.8 3.4,10.2 1.8,8.4 1.2,5.2 1.9,1.8 3.8,0.3 5.6,1.8 5.7,5.4 4.8,8.6 5.2,10 6.4,9.4 7.6,8.5" },
|
|
20
|
+
p: { adv: 8.6, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.9,2 2.4,-4.6 1.8,-9.6 ; 2.8,5 3.4,8.6 5.2,10.2 7.2,9 7.6,5.4 6.4,2 4.2,0.4 2.8,1.4 2.5,3.4 4.4,0.4 6.8,0 8.6,0" },
|
|
21
|
+
q: { adv: 8.4, d: "0,0 1.6,2.6 3.6,6.2 5.2,8.6 6.4,9.6 4.6,10.4 2.4,9.2 1.2,6 1.5,2.4 3.4,0.5 5.2,1.4 6.4,4.4 6.8,9.6 6.6,2 6.2,-5 6.4,-9.4 7.2,-9.8 8.4,-8.4" },
|
|
22
|
+
r: { adv: 7, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.9,5.5 2.8,1.6 3.4,4.6 4.6,8.4 5.8,9.6 6.4,8.4 5.4,7.6 6.2,8.4 7,8" },
|
|
23
|
+
s: { adv: 6.6, d: "0,0 1.2,2.4 2.8,6 4,8.6 4.6,9.8 3.6,9.8 3.5,7.6 4.8,5.8 5,3.6 4.2,1.4 2.8,0.4 1.5,0.8 1.6,1.8 3.2,1.4 5,0.5 6.6,0" },
|
|
24
|
+
t: { adv: 6.4, d: "0,0 1.4,3.4 2.6,8.5 3.2,13 3.4,16.8 3,16.4 3,10 2.8,3.2 3.4,0.6 4.6,0.4 6.4,0 ; 0.6,9.4 3,9.8 5.8,9.2" },
|
|
25
|
+
u: { adv: 8.4, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.7,5.5 2.6,2.2 3.4,0.4 5,0.6 6.4,3.6 7,9.6 6.8,4.6 6.8,1.2 7.6,0.2 8.4,0" },
|
|
26
|
+
v: { adv: 7.6, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.7,5.5 3,2.2 4,0.4 5.2,1.6 6.4,6 7,9 6.4,10 7.6,8.4" },
|
|
27
|
+
w: { adv: 10.4, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.7,5.5 3,2.2 4,0.4 5,2.4 5.4,6 5.5,2.2 6.6,0.4 7.8,2.4 8.6,6 9.2,9 8.8,10 10.4,8.4" },
|
|
28
|
+
x: { adv: 7.4, d: "0,0 1.6,3 3.4,7 5,9.6 4.2,10.4 3,9 3.6,5.6 4.4,2.4 4,0.4 2.6,0.2 2,1.4 3.4,2.2 5.2,4.6 6.4,8.6 6.8,10 7.4,9" },
|
|
29
|
+
y: { adv: 8.2, d: "0,0 1.4,3.4 2.4,8.2 2.8,9.6 2.7,5.5 3,2.2 4,0.4 5.4,2.4 6.4,6 6.8,9.6 6.4,2.6 5.6,-4.6 4,-9 2,-9.8 0.8,-8.4 2,-7 4.6,-5.6 7,-3.4 8.2,0" },
|
|
30
|
+
z: { adv: 7, d: "0,0 1.4,2.6 2.6,6.6 3.4,9 4.4,10 5.8,9.4 3.8,6.4 2.2,3.4 2,0.4 3,-1.6 4.8,-3.6 4.2,-6 2.8,-6.6 2,-5.4 3.4,-4 5.6,-2.2 6.4,0 7,0" },
|
|
31
|
+
};
|
|
32
|
+
/** Capitals drawn for their own: the rest of the capitals are the small letter set tall (see `scriptStrokes`). */
|
|
33
|
+
const UPPER = {
|
|
34
|
+
B: { adv: 14, d: "0,0 1.6,6 3.2,12 5,18 6.2,22.4 7,20 6.2,12 5.4,5 4.6,0.4 6,6.6 9.6,12 13,13.6 13.6,10.6 11,7.6 7,6.4 6,6.2 9,5.6 12.2,3.4 12.8,0.6 11,-1.4 7.8,-1.6 4,0.2 1.4,1 0,0" },
|
|
35
|
+
S: { adv: 11, d: "0,0 2.4,5 5,10 7.6,14.4 9.4,17 8.2,18.8 6,17.2 6.2,14 8.4,11 9.6,7.2 8.4,3 5.8,0.8 3,0.4 1.8,2 3.4,3 6.6,1.6 9,0.4 11,0" },
|
|
36
|
+
};
|
|
37
|
+
const SLANT = 0.3;
|
|
38
|
+
/** A smooth curve through waypoints (a Catmull-Rom spline), as points about 0.8 apart. */
|
|
39
|
+
function through(wp) {
|
|
40
|
+
const out = [];
|
|
41
|
+
for (let i = 0; i + 1 < wp.length; i++) {
|
|
42
|
+
const p0 = wp[Math.max(0, i - 1)], p1 = wp[i], p2 = wp[i + 1], p3 = wp[Math.min(wp.length - 1, i + 2)];
|
|
43
|
+
const n = Math.max(2, Math.ceil(Math.hypot(p2[0] - p1[0], p2[1] - p1[1]) / 0.8));
|
|
44
|
+
for (let j = 0; j < n; j++) {
|
|
45
|
+
const t = j / n, t2 = t * t, t3 = t2 * t;
|
|
46
|
+
out.push([
|
|
47
|
+
0.5 * (2 * p1[0] + (-p0[0] + p2[0]) * t + (2 * p0[0] - 5 * p1[0] + 4 * p2[0] - p3[0]) * t2 + (-p0[0] + 3 * p1[0] - 3 * p2[0] + p3[0]) * t3),
|
|
48
|
+
0.5 * (2 * p1[1] + (-p0[1] + p2[1]) * t + (2 * p0[1] - 5 * p1[1] + 4 * p2[1] - p3[1]) * t2 + (-p0[1] + 3 * p1[1] - 3 * p2[1] + p3[1]) * t3),
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
out.push(wp[wp.length - 1]);
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/** The letter for a character: a drawn capital, a small letter (a capital with no drawing of its own is that letter set 1.7 times as tall), or `undefined`. */
|
|
56
|
+
function letterOf(ch) {
|
|
57
|
+
if (Object.hasOwn(UPPER, ch))
|
|
58
|
+
return { letter: UPPER[ch], k: 1 };
|
|
59
|
+
const low = ch.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
|
|
60
|
+
if (low.length !== 1 || !Object.hasOwn(LOWER, low))
|
|
61
|
+
return undefined;
|
|
62
|
+
return { letter: LOWER[low], k: ch === ch.toUpperCase() && ch !== ch.toLowerCase() ? 1.7 : 1 };
|
|
63
|
+
}
|
|
64
|
+
/** The width of a word in the grid. */
|
|
65
|
+
export function scriptWidth(text) {
|
|
66
|
+
let x = 0;
|
|
67
|
+
for (const ch of [...text]) {
|
|
68
|
+
if (ch === " ")
|
|
69
|
+
x += 5;
|
|
70
|
+
else {
|
|
71
|
+
const l = letterOf(ch);
|
|
72
|
+
if (l !== undefined)
|
|
73
|
+
x += l.letter.adv * l.k;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return x;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A word as pen runs in the grid (y up, the baseline at 0, the left end of the first letter at 0), leaning right, each run with the thickness tier of its segments. Characters with no letter are left out;
|
|
80
|
+
* a space is a gap.
|
|
81
|
+
*/
|
|
82
|
+
export function scriptRuns(text) {
|
|
83
|
+
const runs = [];
|
|
84
|
+
let x = 0;
|
|
85
|
+
for (const ch of [...text]) {
|
|
86
|
+
if (ch === " ") {
|
|
87
|
+
x += 5;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const l = letterOf(ch);
|
|
91
|
+
if (l === undefined)
|
|
92
|
+
continue;
|
|
93
|
+
for (const stroke of l.letter.d.split(";")) {
|
|
94
|
+
const wp = stroke.trim().split(/\s+/).map((p) => p.split(",").map(Number));
|
|
95
|
+
const pts = through(wp).map(([px, py]) => [x + px * l.k + SLANT * py * l.k, py * l.k]);
|
|
96
|
+
const tier = pts.slice(1).map((p, i) => {
|
|
97
|
+
const a = pts[i];
|
|
98
|
+
const dx = p[0] - a[0], dy = p[1] - a[1];
|
|
99
|
+
const down = Math.max(0, -dy / (Math.hypot(dx, dy) || 1));
|
|
100
|
+
return down > 0.62 ? 2 : down > 0.2 ? 1 : 0;
|
|
101
|
+
});
|
|
102
|
+
runs.push({ pts, tier });
|
|
103
|
+
}
|
|
104
|
+
x += l.letter.adv * l.k;
|
|
105
|
+
}
|
|
106
|
+
return runs;
|
|
107
|
+
}
|
|
@@ -4,7 +4,7 @@ import { defineBall } from "./ball.engine.js";
|
|
|
4
4
|
import { truncatedIcosahedron } from "./ball.polyhedra.js";
|
|
5
5
|
import { add, mul, norm } from "./ball.math.js";
|
|
6
6
|
import { blend, mix } from "./ball.core.js";
|
|
7
|
-
import { SOCCER_SIZE } from "./ball.soccer.size.js";
|
|
7
|
+
import { CLASSIC_HOME, SOCCER_SIZE } from "./ball.soccer.size.js";
|
|
8
8
|
const SEAM = "#6b7180";
|
|
9
9
|
export const BALL_SOCCER = /* @__PURE__ */ defineBall({
|
|
10
10
|
id: "ball:soccer",
|
|
@@ -16,11 +16,13 @@ export const BALL_SOCCER = /* @__PURE__ */ defineBall({
|
|
|
16
16
|
base: "#1e2025",
|
|
17
17
|
ground: "#f8f8f6",
|
|
18
18
|
mat: { gloss: 0.8, shade: "#2a3450", grain: { f: 1.1, a: 0.16 } },
|
|
19
|
-
|
|
19
|
+
home: CLASSIC_HOME,
|
|
20
|
+
draw(s, base, _accent, _colors, custom) {
|
|
20
21
|
const t = truncatedIcosahedron();
|
|
21
22
|
let out = "";
|
|
22
23
|
for (const p of t.pentagons)
|
|
23
24
|
out += s.panel(p, base, { ink: true });
|
|
25
|
+
out += custom?.printer?.(s, custom.print, "soccer", [custom.paint?.body ?? "#f8f8f6"]) ?? "";
|
|
24
26
|
out += s.strokes(t.edges, SEAM, 1.15);
|
|
25
27
|
out += s.strokes(t.edges, "#fff", 0.45, { deco: true, opacity: 0.5, dx: 0.3, dy: 0.35 });
|
|
26
28
|
return out;
|
|
@@ -37,7 +39,8 @@ export const BALL_SOCCER_COLOUR = /* @__PURE__ */ defineBall({
|
|
|
37
39
|
base: "#d4283c",
|
|
38
40
|
ground: "#f8f8f6",
|
|
39
41
|
mat: { gloss: 0.8, shade: "#3a2030", grain: { f: 1.1, a: 0.16 } },
|
|
40
|
-
|
|
42
|
+
home: CLASSIC_HOME,
|
|
43
|
+
draw(s, base, _accent, _colors, custom) {
|
|
41
44
|
const t = truncatedIcosahedron();
|
|
42
45
|
const light = blend(base, "#ffffff", 0.45);
|
|
43
46
|
let out = "";
|
|
@@ -47,6 +50,7 @@ export const BALL_SOCCER_COLOUR = /* @__PURE__ */ defineBall({
|
|
|
47
50
|
});
|
|
48
51
|
for (const p of t.pentagons)
|
|
49
52
|
out += s.panel(p, base, { ink: true });
|
|
53
|
+
out += custom?.printer?.(s, custom.print, "soccer", [custom.paint?.body ?? "#f8f8f6", light]) ?? "";
|
|
50
54
|
out += s.strokes(t.edges, mix(base, -0.35), 1.1);
|
|
51
55
|
out += s.strokes(t.edges, "#fff", 0.45, { deco: true, opacity: 0.45, dx: 0.3, dy: 0.35 });
|
|
52
56
|
return out;
|
|
@@ -7,6 +7,8 @@ export interface Tones {
|
|
|
7
7
|
/** A third tone between the light and the mid one, for a third kind of panel. */
|
|
8
8
|
deep: string;
|
|
9
9
|
seam: string;
|
|
10
|
+
/** What a layout lays between its panels and its seams (the print of a ball that has one), if it has any. */
|
|
11
|
+
under?: (s: Surface) => string;
|
|
10
12
|
}
|
|
11
13
|
export type Layout = (s: Surface, t: Tones) => string;
|
|
12
14
|
export declare const classic: Layout;
|
|
@@ -5,7 +5,7 @@ import { blend, mix } from "./ball.core.js";
|
|
|
5
5
|
import { strips18 } from "./ball.family.panelled.js";
|
|
6
6
|
import { truncatedIcosahedron } from "./ball.polyhedra.js";
|
|
7
7
|
import { dodecahedron, gores, propellers14, rhombicuboctahedron } from "./ball.tilings.js";
|
|
8
|
-
import { SOCCER_SIZE } from "./ball.soccer.size.js";
|
|
8
|
+
import { CLASSIC_HOME, SOCCER_SIZE } from "./ball.soccer.size.js";
|
|
9
9
|
const INK = "#1e2025";
|
|
10
10
|
const WHITE = "#f8f8f6";
|
|
11
11
|
const SEAM = "#6b7180";
|
|
@@ -16,6 +16,7 @@ export const classic = (s, t) => {
|
|
|
16
16
|
let out = "";
|
|
17
17
|
for (const p of g.pentagons)
|
|
18
18
|
out += s.panel(p, t.dark, { ink: true });
|
|
19
|
+
out += t.under?.(s) ?? "";
|
|
19
20
|
out += s.strokes(g.edges, t.seam, 1.15);
|
|
20
21
|
return out + lit(s, g.edges);
|
|
21
22
|
};
|
|
@@ -94,7 +95,8 @@ function specOf(construction, way, view) {
|
|
|
94
95
|
base: INK,
|
|
95
96
|
ground: WHITE,
|
|
96
97
|
mat: construction === 6 ? { ...gloss, gloss: 0.9, grain: { f: 0.7, a: 0.07 } } : gloss,
|
|
97
|
-
|
|
98
|
+
home: construction === "classic" ? CLASSIC_HOME : undefined,
|
|
99
|
+
draw: (s, base, accent, _colors, custom) => layout(s, { light: WHITE, dark: base, mid: accent ?? "#dfe2ea", deep: blend(accent ?? "#dfe2ea", base, 0.12), seam: SEAM, under: construction === "classic" ? (u) => custom?.printer?.(u, custom.print, "soccer", [custom.paint?.body ?? WHITE]) ?? "" : undefined }),
|
|
98
100
|
};
|
|
99
101
|
}
|
|
100
102
|
const c = COLOURWAYS[way];
|
|
@@ -102,7 +104,8 @@ function specOf(construction, way, view) {
|
|
|
102
104
|
view,
|
|
103
105
|
base: c.base,
|
|
104
106
|
mat: { ...(construction === 6 ? { ...gloss, gloss: 0.9, grain: { f: 0.7, a: 0.07 } } : gloss), shade: mix(c.base, -0.65) },
|
|
105
|
-
|
|
107
|
+
home: construction === "classic" ? CLASSIC_HOME : undefined,
|
|
108
|
+
draw: (s, base, accent, _colors, custom) => layout(s, { light: base, dark: accent ?? c.accent, mid: blend(base, "#ffffff", 0.4), deep: blend(base, "#ffffff", 0.18), seam: mix(base, -0.5), under: construction === "classic" ? (u) => custom?.printer?.(u, custom.print, "soccer", [base]) ?? "" : undefined }),
|
|
106
109
|
};
|
|
107
110
|
}
|
|
108
111
|
/** The id, and the English and Japanese names, of each construction in each colourway (short, because the name is the accessible name: 26 characters in English and 12 in Japanese at most). */
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import type { PieceSize } from "./ball.core.ts";
|
|
2
2
|
export declare const SOCCER_SIZE: PieceSize;
|
|
3
|
+
/** Where the classic 32-panel ball takes a logo and lettering: the middle of a white hexagon, the way up there, and the view that shows it (the hexagon on the far side is the same, so the label can go there). */
|
|
4
|
+
export declare const CLASSIC_HOME: import("./ball.engine.ts").BallSpec["home"];
|
|
@@ -6,3 +6,11 @@ export const SOCCER_SIZE = {
|
|
|
6
6
|
rule: "IFAB Laws of the Game, Law 2 The Ball, section 2.1 Qualities and measurements",
|
|
7
7
|
note: "Diameter worked out from the middle of the circumference range (68 to 70 cm).",
|
|
8
8
|
};
|
|
9
|
+
/** Where the classic 32-panel ball takes a logo and lettering: the middle of a white hexagon, the way up there, and the view that shows it (the hexagon on the far side is the same, so the label can go there). */
|
|
10
|
+
export const CLASSIC_HOME = {
|
|
11
|
+
c: [-0.577, -0.577, -0.577],
|
|
12
|
+
up: [-0.408, 0.816, -0.408],
|
|
13
|
+
reach: 0.38,
|
|
14
|
+
view: { yaw: 124.5, pitch: -40.8, roll: -6.1 },
|
|
15
|
+
word: "soccer",
|
|
16
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Softball: an optic-yellow ball with red stitches along the seam (88 here, which the rule leaves free).
|
|
2
|
-
import { seamedBall } from "./ball.family.seamed.js";
|
|
2
|
+
import { SEAMED_HOME, seamedBall } from "./ball.family.seamed.js";
|
|
3
3
|
export const BALL_SOFTBALL = /* @__PURE__ */ seamedBall({
|
|
4
4
|
id: "ball:softball",
|
|
5
5
|
en: "Softball",
|
|
@@ -9,6 +9,7 @@ export const BALL_SOFTBALL = /* @__PURE__ */ seamedBall({
|
|
|
9
9
|
b: 0.4,
|
|
10
10
|
view: { yaw: 18, pitch: 28, roll: -10 },
|
|
11
11
|
mat: { gloss: 0.35, shade: "#4c5a10", grain: { f: 1.4, a: 0.12 } },
|
|
12
|
+
home: SEAMED_HOME("softball"),
|
|
12
13
|
groove: "#8a9420",
|
|
13
14
|
stitch: { colour: "#d0262c", count: 88, half: 0.085, width: 0.95, lean: 0.04 },
|
|
14
15
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Surface } from "./ball.engine.ts";
|
|
2
|
+
import type { SafeImage } from "./ball.image.ts";
|
|
3
|
+
import type { V3 } from "./ball.math.ts";
|
|
4
|
+
export type P2 = readonly [number, number];
|
|
5
|
+
/** A flat shape of a drawing: its outlines, its paint, and the width of its stroke, in the drawing's own units. */
|
|
6
|
+
export interface Shape {
|
|
7
|
+
subs: Array<{
|
|
8
|
+
pts: P2[];
|
|
9
|
+
closed: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
fill: string | undefined;
|
|
12
|
+
stroke: string | undefined;
|
|
13
|
+
/** The stroke's width, already scaled by the transforms the shape is under. */
|
|
14
|
+
width: number;
|
|
15
|
+
fillOpacity: number;
|
|
16
|
+
strokeOpacity: number;
|
|
17
|
+
evenodd: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The outlines of a path's data, curves flattened to `steps` segments at most. M, L, H, V, C, S, Q, T, A and Z, absolute and relative. A number that is not one ends the path.
|
|
21
|
+
*/
|
|
22
|
+
export declare function flattenPath(d: string, steps?: number): Array<{
|
|
23
|
+
pts: P2[];
|
|
24
|
+
closed: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* The shapes of a safe drawing in order, with the paint each one ends up with. A gradient is the mean of its stops, `currentColor` is `ink`, an opacity multiplies down the groups, a clip path is not applied,
|
|
28
|
+
* and what is in `defs` or a `clipPath` is not drawn. `box` is the drawing's own box, to size the curves' samples.
|
|
29
|
+
*/
|
|
30
|
+
export declare function shapesOf(img: SafeImage, ink: string): Shape[];
|
|
31
|
+
/** A polyline with points added so that no segment is longer than `step`. */
|
|
32
|
+
export declare function densify(pts: readonly P2[], step: number, closed: boolean): P2[];
|
|
33
|
+
/** What puts a flat point of the drawing on the ball: plane coordinates (y down) to a point of the sphere. */
|
|
34
|
+
export type PlaneMap = (x: number, y: number) => V3;
|
|
35
|
+
/**
|
|
36
|
+
* Shapes drawn on the ball. The drawing's box is fitted into a square of side `size` (radians, in the plane the `map` lays on the ball) and centred; `cap` is the longest segment kept before points are added
|
|
37
|
+
* (radians), so a straight edge curves with the sphere.
|
|
38
|
+
*/
|
|
39
|
+
export declare function drawShapes(s: Surface, shapes: readonly Shape[], box: readonly [number, number, number, number], map: PlaneMap, size: number, o?: {
|
|
40
|
+
opacity?: number;
|
|
41
|
+
colour?: string;
|
|
42
|
+
}): string;
|
|
43
|
+
/**
|
|
44
|
+
* A picture that is not a vector, laid on the ball in triangles. The picture is fitted into a square of side `size` radians; `href` is a data URI that was checked by the caller. Each triangle of a grid of
|
|
45
|
+
* `n` by `n` cells is the picture's piece carried by the one affine map that fits its three corners, clipped to the triangle (grown a little so that no seam shows); a triangle with a corner out of
|
|
46
|
+
* sight is left out. Returns the markup, with the picture in a definition of its own.
|
|
47
|
+
*/
|
|
48
|
+
export declare function drawPicture(s: Surface, href: string, map: PlaneMap, size: number, id: string, n?: number): string;
|