If we were to develop three dimensional voxel shanshui (山水) art, then we would definitely need three dimensional voxelized creator and collector stamps when processing transactions. I almost didn't say anything, but Erik Mahieu and Frederick Wu brought up ambigrams in another recent successful team effort. The purpose of this memo (at min) is to uncover a new mathematical conjecture, which occurs when creating composite ambigrams from Chinese characters in the voxelverse.
Here's the scenario.
An exercise involving a $3 \times 3$ matrix.
九gram = "道江湖金水木山自然";
dat = Rasterize[#] & /@ Characters[九gram];
RastToBitmap[im_, trim_] := With[{
rect = Map[Mod[Mean[#] + 1, 2] &,
Round[ImageData[im]], {2}]},
Map[Join[{0, 0, 0}, #, {0, 0, 0}] &,
rect][[1 + trim ;; -1 - trim, 1 + trim ;; -1 - trim]]]
bitmaps = RastToBitmap[#, 2] & /@ dat;
bitmapIms = Image[Mod[# + 1, 2]] & /@ bitmaps;
Partition[bitmapIms, 3] // Grid
The mission objective that shows up on the teleprompter is to encipher this matrix into the form of $8$ & an extra perfectly decodable voxel ambigrams. The problem (as mentioned by Fredrick) is that the symbols are too high genus for monotonic data to suffice.
Here's the solution I came up with, using the chosen topology of rows + columns + diagonals + knight moves from Square $1$. The lexicon is over three symbols $\{R,G,B\}$ plus another for clear space. After encoding, we can check partial projections:
Partials[gram1_, gram2_, gram3_] := With[{
dat123 = Position[Outer[
gram1[[#1, #2]] gram2[[#2, #3]] gram3[[#3, #1]] & ,
Range[14], Range[14], Range[14], 1], 1]},
MapIndexed[Function[{grams, ind},
Complement[RotateRight[#, ind] & /@ Position[
Outer[grams[[1, #1, #2]] grams[[2, #2, #3]] & ,
Range[14], Range[14], Range[14], 1], 1], dat123]
][#1, #2[[1]] - 1] &, Partition[{gram1, gram2, gram3}, 2, 1, 1]]]
imDat[partials_] := Outer[Image[ReplacePart[
Table[1, {i, 1, 14}, {j, 1, 14}],
# -> 0 & /@ #1[[All, #2]]]] &,
partials[[{2, 3, 1}]], {{1, 2}, {2, 3}, {3, 1}}, 1]
rowDat = Partition[bitmaps, 3];
colDat = Transpose[Partition[bitmaps, 3]];
xDat = {bitmaps[[{1, 5, 9}]], bitmaps[[{3, 5, 7}]],
bitmaps[[{1, 6, 8}]]};
rows = Map[imDat[Partials[Sequence @@ #]] &, rowDat];
cols = Map[imDat[Partials[Sequence @@ #]] &, colDat];
diags = Map[imDat[Partials[Sequence @@ #]] &, xDat];
TableForm /@ rows
TableForm /@ cols
TableForm /@ diags
These matrices in themselves have some interesting structure and are worth more detailed analysis, but for now, we need only one superposition function
Superpose[mat_] := Map[ImageMultiply@mat[[Complement[Range[3], {#}], #]] &, Range[3]]
TableForm[Superpose /@ #] & /@ {rows, cols, diags}
These look correct, but for sake of rigor ++ QA +
MapThread[ImageSubtract[#1, #2] &,
{Flatten[Superpose /@ rows], bitmapIms}]
MapThread[ImageSubtract[#1, #2] &,
{Flatten[Superpose /@ cols],
Flatten[Transpose[Partition[bitmapIms, 3]]]}]
MapThread[ImageSubtract[#1, #2] &,
{Flatten[Superpose /@ diags],
bitmapIms[[{1, 5, 9, 3, 5, 7, 1, 6, 8}]]}]
These $9 \times 3$ black boxes mean proof complete, and it may even be possible to recover the secret extra data "knight's move" by comparing regular first two prints, with odd third (proof unknown). More importantly, since this experiment was successful on 9 varied attempts, we have a new mission objective to prove the conjecture that the same process produces perfectly decodable data for any possible bitmap input.
We can also formulate another similar conjecture for fully layered projections. Using the following functions, we obtain new results in three colors:
Ambigram[TriadData_] := With[
{partials = Partials[Sequence @@ #] &@TriadData},
Graphics3D[ Transpose[{{Blue, Red, Green}, Map[Cuboid, partials, {2}]}]]]
OrthoProj[Ambigram_] := GraphicsGrid[
Transpose[Partition[MapThread[Show[Ambigram,
Boxed -> False, ViewProjection -> "Orthographic",
ViewPoint -> #1, ViewVertical -> #2] &,
{{{0, 0, 1}, {0, 0, -1}, {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}},
{{-1, 0, 0}, {-1, 0, 0}, {0, -1, 0}, {0, -1, 0}, {0, 0, -1}, {0, 0, -1}}}], 2]]]
RGBResults[TriadData_] := With[{amb = Ambigram[TriadData]},
GraphicsRow[Show[#, ImageSize -> 400] & /@ {
Show[amb, ViewProjection -> "Orthographic",
ViewPoint -> {1, 1, 1}, Boxed -> False], OrthoProj[amb]}]]
Face first projections appear to be correct, but is this always the case? Does correctness of Black and White projections imply correctness of RGB projections? These questions must be answered, and theorems proven before we can even begin to think about making voxel NFTs for certain choices of three ASCII characters (or about 玄学X).