UNPKG

9.77 kBMarkdownView Raw
1## Experimenting with Cuneiform
2
3I really like the look and technical design of [Neo-Assyrian cuneiform](https://en.wikipedia.org/wiki/Cuneiform_script#Assyrian_cuneiform), and because my software and company are oriented around creating permanent technical documentation that will stand the test of time, and because I've adopted the *clay* metaphor in my software, it seemed like a good idea to use cuneiform to try to develop a logo.
4
5I'm not an artist and can barely handle a pencil, but I can write code. So I studied the basic elements of the glyphs and broke them down into a single *stalk* element, which can be parametrized to achieve all of the possibilities in Neo-Assyrian. Note that the earlier cuneiforms are not as amenable to this, because they had yet to be standardized and mechanized.
6
7One of my favorite glyphs is `KIR7 (NIM× NÍG.KÁR)` (TBD add good link and definition), which shows different examples of stalks composited together to form a figure:
8
9![](/resources/KIR7_NIM_NIG_KAR_.png)
10
11### Work-in-progress
12
13This is a work-in-progress that may eventually become a separate blog post. Right now, I'm trying to unify all three of the diagrams to use a common definition of my `stalk` function. However, each of the diagrams originally used a custom `stalk` function with slightly different internal parameters, including the arc-depth for the arc at the bottom of the stalk. I need to improve `stalk` to make this parameter explicit so that each of the diagrams can have its appropriate curvature.
14
15### Reusable `stalk` definition
16
17Example of a reusable function, `stalk`, which can be used by subsequent playables. Note the `p5` initial parameter, which must be replaced with the per-playable (sketch) instance of `p5`, by using the construct:
18
19```javascript
20const stalk = window.stalk.bind(this, p5);
21```
22
23I've set this `stalk` definition to `/autoplay` to ensure it executes before the other, optionally playable content.
24
25---
26
27
28```javascript/autoplay/playable
29function stalk(p5, arrowTailX, arrowTailY, arrowWidth, arrowHeight, stalkWidth, stalkHeight, angle, fillColor, bgColor) {
30 // console.log('stalk1', window.p5, this.p5, p5, this, arguments, arrowTailX, arrowTailY, arrowWidth, arrowHeight, stalkWidth, stalkHeight, angle, fillColor, bgColor);
31
32 p5.push();
33 var tx = arrowTailX;
34 var ty = arrowTailY;
35 // p5.fill(bgColor);
36 p5.translate(tx, ty);
37 p5.rotate(angle);
38
39 arrowTailX -= tx;
40 arrowTailY -= ty;
41 var halfWidth = arrowWidth / 2;
42 var thirdWidth = arrowWidth / 3;
43 var quarterWidth = arrowWidth / 4;
44 var threeQuarterWidth = 3 * arrowWidth / 4;
45
46 p5.noStroke();
47 p5.fill(fillColor);
48 p5.triangle(arrowTailX - arrowHeight, arrowTailY, arrowTailX + arrowHeight, arrowTailY, arrowTailX, arrowTailY + arrowHeight);
49
50 p5.fill(fillColor);
51 p5.rect(arrowTailX - stalkWidth / 2, arrowTailY, stalkWidth, stalkHeight + arrowWidth / 4);
52
53 p5.fill(bgColor);
54
55 arrowWidth += arrowWidth * 0.35;
56 arrowTailY -= arrowHeight * 0.2;
57
58 p5.noStroke();
59 // p5.strokeWeight(2);
60 // p5.stroke('yellowgreen');
61 p5.arc(
62 arrowTailX,
63 arrowTailY,
64 arrowWidth,
65 arrowHeight,
66 0 + p5.PI * 0,
67 p5.PI - p5.PI * 0,
68 p5.CHORD);
69
70 p5.pop();
71}
72window.stalk = stalk;
73```
74
75
76
77### Trying to replicate Neo-Assyrian Cuneiform
78
79```p5js/playable/autoplay
80
81var stalk = null;
82
83const ksimImage = p5.loadImage('resources/KSIMGlyph.png');
84const sirImage = p5.loadImage('resources/SIRGlyph.png');
85const bgColor = 'white';
86
87function drawQ() {
88 var centerX = p5.width / 2;
89 var centerY = p5.height / 2;
90 var stalkRadius = 100;
91 var stalkDiameter = 2 * stalkRadius;
92 p5.push();
93 p5.strokeWeight(10);
94 p5.stroke('darkslateblue');
95 p5.fill('aliceblue');
96 p5.ellipse(centerX, centerY, stalkDiameter, stalkDiameter);
97 p5.pop();
98
99 var arrowWidth = 40;
100 var arrowHeight = 15;
101 var stalkWidth = 6;
102 var stalkHeight = 60;
103 var stalkStagger = 0;
104 var numSectors = 10;
105 var sectorSize = p5.TWO_PI / numSectors;
106
107 for (var i = 0; i < numSectors; ++i) {
108 var fillColor = 254 * i / numSectors;
109 var rotationAngle = sectorSize * i;
110 var stalkDeltaX = p5.cos(rotationAngle) * stalkRadius;
111 var stalkDeltaY = p5.sin(rotationAngle) * stalkRadius;
112 stalk(centerX + stalkDeltaX,
113 centerY + stalkDeltaY,
114 arrowWidth,
115 arrowHeight,
116 stalkWidth,
117 stalkHeight,
118 rotationAngle + sectorSize,
119 fillColor,
120 bgColor);
121 }
122}
123
124p5.windowResized = function() {
125 p5.resizeCanvas(p5.windowWidth - 70, 400);
126};
127
128p5.setup = function() {
129 stalk = window.stalk.bind(this, p5);
130 p5.createCanvas(100, 100);
131 p5.windowResized();
132 p5.background('aliceblue');
133 p5.noStroke();
134};
135
136p5.draw = function() {
137 drawQ();
138 p5.fill(0);
139 p5.image(ksimImage, 10, 0, 100, 100);
140 p5.text('KSIM', 30, 100);
141 p5.image(sirImage, p5.width - 150, 0, 100, 100);
142 p5.text('ŜIR', p5.width - 100, 100);
143 p5.frameRate(1);
144};
145```
146
147
148
149## InfoClay Logo
150
151```p5js/playable/autoplay
152
153const bgColor = 'aliceblue';
154var stalk = null;
155
156function drawQ() {
157 var centerX = p5.width / 2;
158 var centerY = p5.height / 2;
159 var stalkRadius = 100;
160 var stalkDiameter = 2 * stalkRadius;
161 var circleDiameter = stalkDiameter + 45;
162 p5.push();
163 p5.strokeWeight(8);
164 p5.stroke('yellowgreen');
165 p5.fill('aliceblue');
166 p5.ellipse(centerX, centerY, circleDiameter, circleDiameter);
167 p5.pop();
168 p5.fill('royalblue');
169 p5.textFont('xkcd');
170 p5.textSize(144);
171 p5.text('I', centerX - 60, centerY + 45);
172 p5.textSize(120);
173 p5.text('C', centerX + 5, centerY + 30);
174 var arrowWidth = 45;
175 var arrowHeight = 25;
176 var stalkWidth = 10;
177 var stalkHeight = 35;
178 var numSectors = 8;
179 var sectorSize = p5.TWO_PI / numSectors;
180
181 for (var i = 0; i < numSectors; ++i) {
182 var fillColor = 254 * (i + 1) / numSectors;
183 var rotationAngle = sectorSize * i;
184 var stalkDeltaX = p5.cos(rotationAngle) * stalkRadius;
185 var stalkDeltaY = p5.sin(rotationAngle) * stalkRadius;
186 stalk(centerX + stalkDeltaX,
187 centerY + stalkDeltaY,
188 arrowWidth,
189 arrowHeight,
190 stalkWidth,
191 stalkHeight,
192 rotationAngle + sectorSize,
193 fillColor,
194 bgColor);
195 }
196}
197
198
199p5.windowResized = function() {
200 p5.resizeCanvas(p5.windowWidth - 70, 300);
201};
202
203p5.setup = function() {
204 stalk = window.stalk.bind(this, p5);
205
206 p5.createCanvas(100, 100);
207 p5.windowResized();
208
209 p5.noStroke();
210};
211
212p5.draw = function() {
213 drawQ();
214 p5.fill(0);
215 p5.frameRate(1);
216};
217```
218
219
220### Quantum Clay Logo
221
222
223```p5js/playable/autoplay
224var stalk = null;
225
226var bgColor = '#400';
227
228function drawRing(sectorSkew, numSectors, centerX, centerY, qMode, cMode) {
229 var stalkRadius = 70;
230 var stalkDiameter = 2 * stalkRadius;
231
232 var arrowHeight = 40;
233 var arrowWidth = 60;
234 var stalkWidth = 10;
235 var stalkHeight = 5;
236 var stalkStagger = 0;
237 var sectorSize = p5.TWO_PI / numSectors;
238
239 for (var i = 0; i < numSectors; ++i) {
240 var fillColor = (254 * (i + 1) / numSectors) % 254;
241 fillColor = p5.color(
242 120,
243 50 + 200 * ((i + 0) % numSectors) / numSectors,
244 200 + 50 * ((i + 0) % numSectors) / numSectors);
245 var rotationAngle = sectorSize * i + sectorSkew;
246 var stalkDeltaX = p5.cos(p5.HALF_PI + rotationAngle) * stalkRadius;
247 var stalkDeltaY = p5.sin(p5.HALF_PI + rotationAngle) * stalkRadius;
248 var stalkWidthOverride = stalkWidth;
249 var stalkHeightOverride = stalkHeight;
250 if (qMode && (i === (numSectors - 1))) {
251 stalkWidthOverride = 4 * stalkWidth;
252 stalkHeightOverride = 1.0 * arrowHeight;
253 }
254 if (cMode && (i === 2)) {
255 // stalkWidthOverride = 2 * stalkWidth;
256 // stalkHeightOverride = 2 * arrowHeight;
257 }
258 if (cMode && ((i > 4) && (i < 6))) {
259 continue;
260 }
261 stalk(centerX + stalkDeltaX,
262 centerY + stalkDeltaY,
263 arrowWidth,
264 arrowHeight,
265 stalkWidthOverride,
266 stalkHeightOverride,
267 rotationAngle,
268 fillColor,
269 bgColor);
270 }
271}
272
273function drawQ() {
274 drawRing(0, 6, p5.width * 0.3, p5.height * 0.375, true, false);
275}
276
277function drawC() {
278 var skew = -0.165 * p5.PI;
279 drawRing(skew, 6, p5.width * 0.748, p5.height * 0.635, false, true);
280}
281
282function drawBox() {
283 var margin = 1;
284 var arrowWidth = 60;
285 var arrowHeight = arrowWidth / 2;
286 var stalkWidth = 10;
287 var fillColor = 'royalblue';
288 // p5.background('lightyellow');
289 // p5.fill('orange');
290 // p5.stroke('green');
291
292 stalk(margin + arrowWidth / 2,
293 p5.height - (margin + arrowWidth / 2),
294 arrowWidth,
295 arrowHeight,
296 stalkWidth,
297 p5.height * 0.4 - 2 * (margin + arrowWidth),
298 p5.PI,
299 fillColor,
300 bgColor);
301 stalk(p5.width - (margin + arrowWidth / 2),
302 margin + arrowWidth / 2,
303 arrowWidth,
304 arrowHeight,
305 stalkWidth,
306 p5.height * 0.4 - 2 * (margin + arrowWidth),
307 0,
308 fillColor,
309 bgColor);
310 stalk(p5.width * 0.4 + margin + arrowWidth / 2,
311 margin + arrowWidth / 2,
312 arrowWidth,
313 arrowHeight,
314 stalkWidth,
315 p5.width * 0.6 - 2 * (margin + arrowWidth),
316 p5.PI + p5.HALF_PI,
317 fillColor,
318 bgColor);
319 stalk(p5.width * 0.6 - (margin + arrowWidth / 2),
320 p5.height - (margin + arrowWidth / 2),
321 arrowWidth,
322 arrowHeight,
323 stalkWidth,
324 p5.width * 0.6 - 2 * (margin + arrowWidth),
325 p5.HALF_PI,
326 fillColor,
327 bgColor);
328}
329
330p5.setup = function() {
331 stalk = window.stalk.bind(this, p5);
332
333 p5.createCanvas(500, 500);
334 p5.background(bgColor);
335 p5.noStroke();
336};
337
338p5.draw = function() {
339 drawQ();
340 drawC();
341 drawBox();
342 p5.frameRate(1);
343};
344```
345
346---
347
348[Back to Home](:@Home)
349