3D text charts: surfaces, scatter, bars, and lines
@glyphcss/charts/3d builds a mark, and renderGlyphChart3d(mark, options) turns it into text. Drag any chart to turn it; [ Code ] shows the exact call.
npm install @glyphcss/charts glyphcssSurface
Section titled “Surface”
k req
⡄
⡇ ⣀⣤⣤⣀⣀
⡇ ⣀⣠⣴⣶⣿⠿⠞⠛⠉⠉⢧⡀
3 + 6⣀⣤⣴⣾⡿⠟⠛⠉⠉⢯⡉⠙⠒⠲⠤⢤⣳⣄
⡇ ⢀⣀⣤⣴⣶⣿⡿⠟⠋⠉⢯⡉⠓⠲⠤⢤⣀⣳⡄⢀⣠⠴⠚⠉⢻⣧⡀⣀⣠⡴⣖⣦⣤⣄
⡇ 4⣀⣤⣴⣾⣿⢿⠟⠛⠻⡗⠒⠦⠤⣄⣀⡳⡄⢀⣀⡤⠴⠚⠻⡿⢤⡀ ⢧⠙⣿⠿⣟⣉⣁⣀⣈⠳⣄
⡇ ⣠⣴⢿⠋⠉⢻⡓⠒⠦⠤⢤⣀⣙⢦ ⣀⣠⠴⠛⠻⡿⣄⡀ ⢳ ⠉⠓⠦⣄⠈⣇ ⠳⣄ ⣀⣠⠬⠟⠛⢳⡀
⡇ 2 ⢀⡞⠉⡴⠋⡼⣡⣞⡽⣄ ⣀⣠⠼⠛⢿⢧⣀ ⢹⡀⠙⠲⢤⡀⠈⣇ ⠈⢙⣺⣦⡖⠚⢻⡓⠲⠤⣄⣀ ⢳⡀ 3.6█
2 + ⢠⣾⠴⠋⡄⡾⠛⠉⣡⠞⡟⣶⣏⠁ ⠘⡆⠈⠓⠦⣄ ⢳ ⠉⠳⢼⣄⡤⠖⠚⠉ ⠹⡝⠲⣄⡳⡄ ⠈⣉⡽⠷⡄ █
⡇ ⣠⠿⠛⠉⠗⠿⠁⡴⠚⠁⡞⡞⣽⡎⠙⠦⣄⡀ ⢹ ⠈⠙⠮⣧⣠⠤⠖⠋⠉⢻⡓⢦⣀ ⢳ ⠙⢻⣤⣖⣋⠁ ⠹⣄ 2.95▛
⡇ ⢀⣠⣴⠷ ⠞⠁⠼⡵⡋⡤⠶⠛⠉⠉⠋⠹⡄ ⠙⠲⣌⣇⢀⣠⠤⠖⠋⠙⣟⠦⣄ ⢧ ⠈⠓⠦⣄⠈⢧ ⣠⠏⠘⣆⠈⠉⠓⠲⠤⢼⣆ ▛
⡇ ⢀⣠⡴+⣟⡛⣹⣿⣚⣡⡤⠾⠛⠉⠉⠉ ⢳⡀⣀⣠⠴⠒⠻⡿⢤⣀ ⠸⡄⠈⠙⠲⣄⡈⣇ ⠈⣙⣺⣾⠥⢤⣀⣘⣆⣠⠤⠖⠚⠉⠉⠳⡄ 2.3▀
⢧⣶⡿⠛⣒⣲⣶⣿⣿⣿⠿⠋⠛⠉ ⢿⢧⣀ ⢹⡀⠈⠙⠦⣄⡀⢹⡀ ⣙⣺⣦⣖⡚⠉⠁ ⠘⣆ ⢠⠏⠻⡍⠉⠙⠒⠒⢲⣽⡦ ▀
1 +⠈⠙⠻⢿⣒⠚⠋⠉ ⠘⡆⠈⠓⠦⣄ ⢳ ⠉⣓⣷⣴⡒⠋⠁ ⠘⣆⠉⠙⠒⠦⢤⣈⣧⢠⢏⣀⣀⣹⠦⠴⠒⠋⠉ 1.65▘
⠈⠉⠓+⣄⡀ ⢹⡀ ⠈⠙⠮⣧⣠⠴⠒⠋⠁⠈⢧⠉⠙⠲⢤⣀⡘⣆ ⣀⣠⠴⠛⠉⠉ ▘
⠉⠓⠦⢤⣀ ⢧⣠⠤⠖⠚⠉⠉⢯⠙⠒⠦⣄⣀⠈⢧ ⢀⣀⡭⠿⠒⠋⠁ 1
⠈+⠲⢤⣀⡀ ⠈⢯⠓⠲⢤⣀⡀⠈⢧ ⢈⣩⠿⠓⠋⠉
0 ⠉⠓⠦⣄⡀ ⠈⢧ ⠉⢙⣺⡧⠴⠚⠉
5 +⠉⠓⠲⢤⣀ ⠈⠧⠴⠒⠋⠉
⠈⠙+⢤⣀
10
Hour
15
20 drag to rotate
Code
import { glyphChartSurface, renderGlyphChart3d } from "@glyphcss/charts/3d";
const mark = glyphChartSurface({
z: [
[1, 1.02, 1.11, 1.48, 2.25, 2.94, 3.3, 3.43, 3.1, 2.41, 1.72, 1.28],
[1, 1.02, 1.11, 1.48, 2.25, 2.94, 3.3, 3.43, 3.1, 2.41, 1.72, 1.28],
[1, 1.02, 1.11, 1.48, 2.25, 2.94, 3.3, 3.43, 3.1, 2.41, 1.72, 1.28],
[1, 1.02, 1.11, 1.48, 2.25, 2.94, 3.3, 3.43, 3.1, 2.41, 1.72, 1.28],
[1, 1.02, 1.11, 1.48, 2.25, 2.94, 3.3, 3.43, 3.1, 2.41, 1.72, 1.28],
[1, 1.01, 1.05, 1.21, 1.56, 1.93, 2.21, 2.33, 2.16, 1.77, 1.4, 1.16],
[1, 1.01, 1.05, 1.21, 1.56, 1.93, 2.21, 2.33, 2.16, 1.77, 1.4, 1.16]
]
}, {
x: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22],
y: [1, 2, 3, 4, 5, 6, 7]
}, {
axes: {
x: {
title: "Hour",
ticks: 4
},
y: {
title: "Day",
ticks: 4
},
z: {
title: "k req",
ticks: 3
}
}
});
const { text } = renderGlyphChart3d(mark, {
target: "web",
width: 88,
height: 34,
charset: "braille"
});
console.log(text); glyphChartSurface({ z }, channels?, options?) takes a row-major grid; x/y channels place the columns and rows. Here: requests per hour across a week.
Scatter
Section titled “Scatter”
z
⡄ ⣠⡀ ⢀⣄
8 + ⣴⢷⣄⢀ ⢠⣾⣯⢧⣦ ⣴⡿⠹⣧
⡇ ⢀ ⣠⣦⣼⣇⣈⣿⣟⣷⣿⢁⢻⣿⠇ ⢀ ⢿⡒⢒⡿
⡇ ⣰⣟⢷⣄ ⣰⡟⠘⣿⢿⣼⣯⠤⢼⡇⣿⣿⠃ ⣴⢳⡄ 8 ⣰⣟⣷⣄ ⠙⠛⢳⡄
6 + ⣿⠤⠬⣷ ⠻⣍⠩⣿⣟⣷⣿⠷⠏⣿⡬⣿⡟ 6⣏ ⢳⡆ ⢰⣿⠤⢼⡟⡀⢠⣾⣯⡓⢳⡆
⡇ ⠈⠇⠞⠁ ⠈⢹⣿⣀⣸⡷⢤⣽⣇⣿⡏⠁ ⠙⣎⠉⡽⠃ ⣀ ⢀⣽⠷⠏⠯⢧⣿⣀⣙⣿⡽⠃
⡇ ⠈⠳ ⠚⠁⠶⠋⢠⠞⠁ ⠈⠉ ⣀⡤⠴⠒⠋⠁ ⣾⠃⠹⣷⠒⣺⣿⣧⠰⠋ ⢀⣴⣄
⡇ 2 ⢀⣠⡾⣶⡚⠉⠁ + ⠻⠍⢩⡟⣿⣿⢳⢻⣷⡾⣦⡀ ⢰⡿⠁⢳⣷
4 + ⢀⣠⠤⠖⠚+⣿⣀⣘⣶ ⣩⣿⣿⣿⢿⠓⣺⣿⣿⣞⣶ ⠘⠏⠉⠽⠃
0⡇ ⣀⣠⠴⠒⠋⠉ ⠈⠻ ⠰⠋ ⣿⠽⢭⣿⣿⣻⡏⣿⣃⠸⣯ ⠉⠁
⡇ ⣀⡤⠴⠚⠉⠁ + ⢀⣴⣄ ⣠⣾⣿⠾⠳ ⠚⠁⠹⠈⢩⠟
⡇ ⢀⣀⡤⠖⠚+⠁ ⢀⣾⠁⢳⣷⢰⣿⠈⢿⣷ ⠉⠁
2 +⣖⠋⠉ ⣴⣻⢯⠉⠽⡃⡘⠏⠉⡽⠃⣄
+⠈⠙⠲+⣀ ⢀⣼⣏⣿⣷⣭⣿⣻⣿⡎⢹⣏⣀⣳⣧⡀
⠈⠙⠲⠤⣄⡀ ⢀⣾⠁⢻⣿⣷⣿⣇⣉⣿⣷⢻⣿ ⣾⣋⢿⣄
⠉+⠦⣄⡀ ⠘⢏⣿⣿⣿⣿⣿⢾⠐⣻⣏⣀⣻⣿⣧⠤⢼⡆
⠉⠓⠲⢤⣀ ⢸⣯⠤⢼⡟⠏⠉ ⠙⢦ ⠞⠁⠙⠦⠏
0 +⠙⠲⢤⣀ ⠙⠆⠏⠉
⠈⠙⠒+⣄⡀
2 ⠉⠓⠦⣄⡀
⠉+
4 x
6
drag to rotate
Code
import { glyphChartScatter3d, renderGlyphChart3d } from "@glyphcss/charts/3d";
const mark = glyphChartScatter3d([
{
x: -0.9,
y: 1.1,
z: 5.6,
group: "Search"
},
{
x: 3.5,
y: 2.7,
z: 4.7,
group: "Search"
},
{
x: 2.8,
y: 0.7,
z: 8,
group: "Search"
},
{
x: 2.5,
y: 3.2,
z: 6.1,
group: "Search"
},
{
x: 1.2,
y: 3.2,
z: 6.9,
group: "Search"
},
{
x: 1.9,
y: 2.3,
z: 7.2,
group: "Search"
},
{
x: 2,
y: 2.2,
z: 6.5,
group: "Search"
},
{
x: 1.9,
y: 2,
z: 5.8,
group: "Search"
},
{
x: 1.8,
y: 0.9,
z: 6.3,
group: "Search"
},
{
x: 0.2,
y: 1.7,
z: 6.2,
group: "Search"
},
{
x: 1.3,
y: 2.8,
z: 5.8,
group: "Search"
},
{
x: 1.9,
y: 2.1,
z: 6.5,
group: "Search"
},
{
x: 2,
y: 1.4,
z: 6.3,
group: "Search"
},
{
x: 1.5,
y: 1.3,
z: 7.6,
group: "Search"
},
{
x: 6.6,
y: 3.6,
z: 3,
group: "Checkout"
},
{
x: 6.6,
y: 1.1,
z: 2.5,
group: "Checkout"
},
{
x: 4.7,
y: 3,
z: 2.4,
group: "Checkout"
},
{
x: 5.6,
y: 2.8,
z: 3.8,
group: "Checkout"
},
{
x: 5.2,
y: 3,
z: 2.7,
group: "Checkout"
},
{
x: 5.6,
y: 2.4,
z: 1.9,
group: "Checkout"
},
{
x: 6.6,
y: 3.1,
z: 4.1,
group: "Checkout"
},
{
x: 5.9,
y: 3.8,
z: 3.6,
group: "Checkout"
},
{
x: 7,
y: 3.8,
z: 2.2,
group: "Checkout"
},
{
x: 5.4,
y: 3.4,
z: 2.4,
group: "Checkout"
},
{
x: 6,
y: 2.6,
z: 2.5,
group: "Checkout"
},
{
x: 6.8,
y: 2.1,
z: 3.2,
group: "Checkout"
},
{
x: 7.1,
y: 2.6,
z: 2.5,
group: "Checkout"
},
{
x: 4.8,
y: 2.5,
z: 2,
group: "Checkout"
},
{
x: 4.1,
y: 6.4,
z: 2.9,
group: "Profile"
},
{
x: 5.2,
y: 6.5,
z: 3.3,
group: "Profile"
},
{
x: 2.8,
y: 7.3,
z: 3.9,
group: "Profile"
},
{
x: 3.7,
y: 6.5,
z: 3.1,
group: "Profile"
},
{
x: 3.5,
y: 6,
z: 4.3,
group: "Profile"
},
{
x: 2.8,
y: 8.5,
z: 4.1,
group: "Profile"
},
{
x: 4.6,
y: 6.2,
z: 4.1,
group: "Profile"
},
{
x: 3.6,
y: 7.4,
z: 4.4,
group: "Profile"
},
{
x: 4.8,
y: 8.3,
z: 3.4,
group: "Profile"
},
{
x: 4.4,
y: 5.4,
z: 6.3,
group: "Profile"
},
{
x: 4,
y: 6.6,
z: 3.4,
group: "Profile"
},
{
x: 5.1,
y: 6.6,
z: 3.8,
group: "Profile"
},
{
x: 3.7,
y: 6.1,
z: 3,
group: "Profile"
},
{
x: 3.9,
y: 7.2,
z: 6.5,
group: "Profile"
}
], {
series: "group"
}, {
markerSize: 0.07,
axes: {
x: {
ticks: 3
},
y: {
ticks: 3
},
z: {
ticks: 3
}
}
});
const { text } = renderGlyphChart3d(mark, {
target: "web",
width: 88,
height: 34,
charset: "braille"
});
console.log(text); glyphChartScatter3d(records, channels?, options?) reads x/y/z fields. Use series for groups, color for a continuous value, size for marker size.
Parametric surfaces
Section titled “Parametric surfaces”
z
⢀⣀⣠⣤⣤⣤⣤⢤⣤⣤⣤⣀⣀⡀
⢀ ⣀⣤⣶⣿⣿⠿⣿⣟⢹⣯⢹⢉⣽⣏⣩⡿⣻⣿⢿⣷⣶⣤⣀
⢸ ⢀⣤⣾⣿⡿⣟⣿⡾⣾⣹⡮⢽⡟⣻⠛⣺⡛⢺⠯⣽⣹⣾⢴⡿⣿⣿⣷⣄
⢸+ ⣾⣾⣿⣿⣽⣿⣿⡿⣟⣆⣧⡼⣷⠛⣶⢻⢧⡼⣧⣇⡞⣷⣿⣿⣷⣿⣿⣻⣷⡄
⢸ ⣼⣻⣟⣿⣭⣿⣿⣿⣿⣿⣿⣸⠷⣟⠒⣟⢺⠾⡧⢽⣸⣟⣷⣿⣿⣟⡿⡿⣿⢷⢷
⢸+ ⢸⣿⡟⢾⣏⢳⣼⣩⢿⡟⣿⣿⣿⣿⣿⣶⣿⣾⣾⣷⣾⣿⣿⣿⡛⣏⡽⢳⣇⡽⣿⣿⡆
⢸ 0⡿⢳⡟⡎⡽⠛⢦⡾⣞⣩⣯⡖⠯⣿⣧⣾⡿⣿⣇⣿⠓⢮⣧⣩⠿⣗⢫⢷⣠⢿⣯⡇
⢸ ⣿⣿⢾⣁⢧⣧⠖⢻⢁⡴⣻ ⢉⡽⡏⢉⡽⡿⣍⠉⢹⢯⡉⢸⡳⢤⣸⣸ ⣿⣴⡏⣧ 0.41█
0 ⢸+ -1 ⣿⢸⡼⣨⢿⡗⠦⡿⣏⣀⣧⣞⠉⢸⣡⠏ ⡇⠈⢧⣸ ⢙⣦⣇⡤⢽⣷⡋⢹⡼⢳⣸ █
-2 ⢻⠻⣷⠃⡞⠹⡄⡇⢀⡞⡇⠈⣩⢿⢯⠉⠉⡿⣍⠉⢹⢯⡉ ⡇⢠⠏⡇⠹⣼⣧⢼⠃ 0.205▛
⢸+ ⢀⣠⠤⠖⢺⣿⢿⡝⡷⠤⣽⣷⡋ ⣇⡼⠁⢸⠈⠳⡄⡇⠈⢧⡘⡆⠹⣄⣧⣏⣠⡷⠚⡿⠇⡞⡇ ▛
⢸ ⣀⣠⠴⠒⠋⠉ ⣿⢾⡹⣷⢠⠞⡿⣍⠉⡿⡝⠒⢺⠒⠒⣻⡗⠒⠒⣻⡗⠒⡿⡿⣅ ⡇⡞⢸⣨⡟⠁ 0▀
⢸+⢀⣀⡤⠴⠚⠉⠁+ ⠘⣯⡏⣿⣯⣄⣇⡘⢦⡇⠙⢦⢸⢀⡞⠁⡇⣠⠞⢱⢣⠞⠁⡇⣈⣳⣿⠖⡿⣽⠁ ▀
⠘+⣍⡀ ⠈⠻⣥⣯⣳⣻⢯⡉⣿⣝⠚⢻⠛⠒⣲⡟⠓⢒⣾⠛⢚⣽⡏⡵⢻⠙⡞⠖⠃ -0.205▘
⠉⠓⠦⣄⡀ ⠈⠛⠻⠻⢷⢿⢾⣬⣝⣮⣧⣞⣁⣧⣞⣉⣸⣴⣫⣼⠾⠿⠋⠋⠁ ▘
⠉⠙+⢤⣀ ⠉⠉⠙⠓⠛⠛⠓⠑⠋⠛⠛⠛⠉⠉⠁ -0.41
⠈⠙⠲⢤⣀
-2 ⠈+⠓⠦⣄⡀
⠉⠓⠦⣄⣀
-1 +⠙⠲⢤⣀
⠈⠙⠲⠤
0 +
x
1
drag to rotate
Code
import { glyphChartParametric3d, renderGlyphChart3d } from "@glyphcss/charts/3d";
const mark = glyphChartParametric3d({
x: [
[1.42, 1.38, 1.28, 1.11, 0.89, 0.62, 0.32, 0, -0.32, -0.62, -0.89, -1.11, -1.28, -1.38, -1.42, -1.38, -1.28, -1.11, -0.89, -0.62, -0.32, 0, 0.32, 0.62, 0.89, 1.11, 1.28, 1.38],
[1.38, 1.34, 1.24, 1.08, 0.86, 0.6, 0.31, 0, -0.31, -0.6, -0.86, -1.08, -1.24, -1.34, -1.38, -1.34, -1.24, -1.08, -0.86, -0.6, -0.31, 0, 0.31, 0.6, 0.86, 1.08, 1.24, 1.34],
[1.26, 1.23, 1.14, 0.99, 0.79, 0.55, 0.28, 0, -0.28, -0.55, -0.79, -0.99, -1.14, -1.23, -1.26, -1.23, -1.14, -0.99, -0.79, -0.55, -0.28, 0, 0.28, 0.55, 0.79, 0.99, 1.14, 1.23],
[1.09, 1.07, 0.99, 0.85, 0.68, 0.47, 0.24, 0, -0.24, -0.47, -0.68, -0.85, -0.99, -1.07, -1.09, -1.07, -0.99, -0.85, -0.68, -0.47, -0.24, 0, 0.24, 0.47, 0.68, 0.85, 0.99, 1.07],
[0.91, 0.88, 0.82, 0.71, 0.57, 0.39, 0.2, 0, -0.2, -0.39, -0.57, -0.71, -0.82, -0.88, -0.91, -0.88, -0.82, -0.71, -0.57, -0.39, -0.2, 0, 0.2, 0.39, 0.57, 0.71, 0.82, 0.88],
[0.74, 0.72, 0.67, 0.58, 0.46, 0.32, 0.16, 0, -0.16, -0.32, -0.46, -0.58, -0.67, -0.72, -0.74, -0.72, -0.67, -0.58, -0.46, -0.32, -0.16, 0, 0.16, 0.32, 0.46, 0.58, 0.67, 0.72],
[0.62, 0.61, 0.56, 0.49, 0.39, 0.27, 0.14, 0, -0.14, -0.27, -0.39, -0.49, -0.56, -0.61, -0.62, -0.61, -0.56, -0.49, -0.39, -0.27, -0.14, 0, 0.14, 0.27, 0.39, 0.49, 0.56, 0.61],
[0.58, 0.57, 0.52, 0.45, 0.36, 0.25, 0.13, 0, -0.13, -0.25, -0.36, -0.45, -0.52, -0.57, -0.58, -0.57, -0.52, -0.45, -0.36, -0.25, -0.13, 0, 0.13, 0.25, 0.36, 0.45, 0.52, 0.57],
[0.62, 0.61, 0.56, 0.49, 0.39, 0.27, 0.14, 0, -0.14, -0.27, -0.39, -0.49, -0.56, -0.61, -0.62, -0.61, -0.56, -0.49, -0.39, -0.27, -0.14, 0, 0.14, 0.27, 0.39, 0.49, 0.56, 0.61],
[0.74, 0.72, 0.67, 0.58, 0.46, 0.32, 0.16, 0, -0.16, -0.32, -0.46, -0.58, -0.67, -0.72, -0.74, -0.72, -0.67, -0.58, -0.46, -0.32, -0.16, 0, 0.16, 0.32, 0.46, 0.58, 0.67, 0.72],
[0.91, 0.88, 0.82, 0.71, 0.57, 0.39, 0.2, 0, -0.2, -0.39, -0.57, -0.71, -0.82, -0.88, -0.91, -0.88, -0.82, -0.71, -0.57, -0.39, -0.2, 0, 0.2, 0.39, 0.57, 0.71, 0.82, 0.88],
[1.09, 1.07, 0.99, 0.85, 0.68, 0.47, 0.24, 0, -0.24, -0.47, -0.68, -0.85, -0.99, -1.07, -1.09, -1.07, -0.99, -0.85, -0.68, -0.47, -0.24, 0, 0.24, 0.47, 0.68, 0.85, 0.99, 1.07],
[1.26, 1.23, 1.14, 0.99, 0.79, 0.55, 0.28, 0, -0.28, -0.55, -0.79, -0.99, -1.14, -1.23, -1.26, -1.23, -1.14, -0.99, -0.79, -0.55, -0.28, 0, 0.28, 0.55, 0.79, 0.99, 1.14, 1.23],
[1.38, 1.34, 1.24, 1.08, 0.86, 0.6, 0.31, 0, -0.31, -0.6, -0.86, -1.08, -1.24, -1.34, -1.38, -1.34, -1.24, -1.08, -0.86, -0.6, -0.31, 0, 0.31, 0.6, 0.86, 1.08, 1.24, 1.34]
],
y: [
[0, 0.32, 0.62, 0.89, 1.11, 1.28, 1.38, 1.42, 1.38, 1.28, 1.11, 0.89, 0.62, 0.32, 0, -0.32, -0.62, -0.89, -1.11, -1.28, -1.38, -1.42, -1.38, -1.28, -1.11, -0.89, -0.62, -0.32],
[0, 0.31, 0.6, 0.86, 1.08, 1.24, 1.34, 1.38, 1.34, 1.24, 1.08, 0.86, 0.6, 0.31, 0, -0.31, -0.6, -0.86, -1.08, -1.24, -1.34, -1.38, -1.34, -1.24, -1.08, -0.86, -0.6, -0.31],
[0, 0.28, 0.55, 0.79, 0.99, 1.14, 1.23, 1.26, 1.23, 1.14, 0.99, 0.79, 0.55, 0.28, 0, -0.28, -0.55, -0.79, -0.99, -1.14, -1.23, -1.26, -1.23, -1.14, -0.99, -0.79, -0.55, -0.28],
[0, 0.24, 0.47, 0.68, 0.85, 0.99, 1.07, 1.09, 1.07, 0.99, 0.85, 0.68, 0.47, 0.24, 0, -0.24, -0.47, -0.68, -0.85, -0.99, -1.07, -1.09, -1.07, -0.99, -0.85, -0.68, -0.47, -0.24],
[0, 0.2, 0.39, 0.57, 0.71, 0.82, 0.88, 0.91, 0.88, 0.82, 0.71, 0.57, 0.39, 0.2, 0, -0.2, -0.39, -0.57, -0.71, -0.82, -0.88, -0.91, -0.88, -0.82, -0.71, -0.57, -0.39, -0.2],
[0, 0.16, 0.32, 0.46, 0.58, 0.67, 0.72, 0.74, 0.72, 0.67, 0.58, 0.46, 0.32, 0.16, 0, -0.16, -0.32, -0.46, -0.58, -0.67, -0.72, -0.74, -0.72, -0.67, -0.58, -0.46, -0.32, -0.16],
[0, 0.14, 0.27, 0.39, 0.49, 0.56, 0.61, 0.62, 0.61, 0.56, 0.49, 0.39, 0.27, 0.14, 0, -0.14, -0.27, -0.39, -0.49, -0.56, -0.61, -0.62, -0.61, -0.56, -0.49, -0.39, -0.27, -0.14],
[0, 0.13, 0.25, 0.36, 0.45, 0.52, 0.57, 0.58, 0.57, 0.52, 0.45, 0.36, 0.25, 0.13, 0, -0.13, -0.25, -0.36, -0.45, -0.52, -0.57, -0.58, -0.57, -0.52, -0.45, -0.36, -0.25, -0.13],
[0, 0.14, 0.27, 0.39, 0.49, 0.56, 0.61, 0.62, 0.61, 0.56, 0.49, 0.39, 0.27, 0.14, 0, -0.14, -0.27, -0.39, -0.49, -0.56, -0.61, -0.62, -0.61, -0.56, -0.49, -0.39, -0.27, -0.14],
[0, 0.16, 0.32, 0.46, 0.58, 0.67, 0.72, 0.74, 0.72, 0.67, 0.58, 0.46, 0.32, 0.16, 0, -0.16, -0.32, -0.46, -0.58, -0.67, -0.72, -0.74, -0.72, -0.67, -0.58, -0.46, -0.32, -0.16],
[0, 0.2, 0.39, 0.57, 0.71, 0.82, 0.88, 0.91, 0.88, 0.82, 0.71, 0.57, 0.39, 0.2, 0, -0.2, -0.39, -0.57, -0.71, -0.82, -0.88, -0.91, -0.88, -0.82, -0.71, -0.57, -0.39, -0.2],
[0, 0.24, 0.47, 0.68, 0.85, 0.99, 1.07, 1.09, 1.07, 0.99, 0.85, 0.68, 0.47, 0.24, 0, -0.24, -0.47, -0.68, -0.85, -0.99, -1.07, -1.09, -1.07, -0.99, -0.85, -0.68, -0.47, -0.24],
[0, 0.28, 0.55, 0.79, 0.99, 1.14, 1.23, 1.26, 1.23, 1.14, 0.99, 0.79, 0.55, 0.28, 0, -0.28, -0.55, -0.79, -0.99, -1.14, -1.23, -1.26, -1.23, -1.14, -0.99, -0.79, -0.55, -0.28],
[0, 0.31, 0.6, 0.86, 1.08, 1.24, 1.34, 1.38, 1.34, 1.24, 1.08, 0.86, 0.6, 0.31, 0, -0.31, -0.6, -0.86, -1.08, -1.24, -1.34, -1.38, -1.34, -1.24, -1.08, -0.86, -0.6, -0.31]
],
z: [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18],
[0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33],
[0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41],
[0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41],
[0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33],
[0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.18],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[-0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18],
[-0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33],
[-0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41],
[-0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41, -0.41],
[-0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33, -0.33],
[-0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18, -0.18]
]
}, {
wrapU: true,
wrapV: true
});
const { text } = renderGlyphChart3d(mark, {
target: "web",
width: 88,
height: 34,
charset: "braille"
});
console.log(text); glyphChartParametric3d({ x, y, z, value? }, options?) takes equal-shaped coordinate grids. wrapU/wrapV close the seams, as in this torus. glyphChart3dSphereGrid and glyphChart3dTorusGrid generate grids for you.
Revenue
8 ⢸+ ⣀⡤⢶⠦⣄⡀ ⣀
⢸ ⢠⣴⡚⠉⠁ ⠘ ⠉⢓⣦⣤⣶⢿⢷⠦⣄⡀⣀⡤⠴⠒⠋⢹⠙⠲⢤⣀
⢸ ⢸ ⠉⠓⠦⣄⣀⡤⢶⠾⣍⡀ ⢀⣩⣷⣦⣤⣶⣤⣼⡀⢀⣀⡬⠽⣆⣀⣤⣄⡀
6 ⢸+ ⢸ ⡇ ⢸ ⠉⠓⠦⡤⠖⢫⣽⡚⠉⡇ ⢸ ⠈⠙⣿⣶⣞⡉⡏ ⢸ ⠉⠓⠦⣄⣀⡤⢶⢤⣀ ⣀⣤⣄⡀
⢸ ⣀⣠⠴⡦⣄⣸ ⣀⣠⣧⣀⢸ ⡇ ⢸ ⠉⠓⠦⣄⣀⡤⠴⢒⣋⡭⡷⡷⣿⣻⢿⣦⣤⣶⠛⠉ ⠸ ⣈⡽⠶⢾⡉⠁⢸ ⠉⠓⠦⣄⡀
⢸⣴⡚⠉⠁ ⠇⢠⣽⠓⠯⣍⠁ ⡇⠈⠙⠲⣤⣠⠤⢶⡧⣄⣸ ⡇ ⢸⠻⢤⣀ ⢸ ⢀⣩⣿⡿⡶⢶⣻⣳⠦⣟⡙⠲⢤⣀ ⢀⣠⠤⠖⠚⠉⡇ 7.1█
4 ⢸ ⠉⠓⠦⣄⣀⡤⢼⠈⠙⠲⢤⣀ ⣀⣴⢾⣛⠋ ⢸ ⠉⠙⣲⣤⣀⣤⣇⡀⢸ ⠈⠙⠲⡤⠖⠋⠉ ⣇ ⢸ ⢀⣩⠷⡆⠈⢹⠉ ⡇ █
⢸ ⡇ ⢸ ⠈⡏⠁⢸ ⠈⠙⠲⢤⣀⡤⢖⣺⠽⠓⢻⠁⢸ ⠉⢻⠲⢤⣀ ⡇ ⡇⠙⠲⡤⠖⠋⠉ ⡇ ⢸ ⡇ 5.325▛
2 ⢸ ⡇ ⢸ ⡇ ⢸ ⡇ ⢸⠉⠓⠦⣄⡀ ⣀⡤⠴⠒⠋⢹ ⡇ ⡇ ⡇ ⡇ ⢸ ⡇ ▛
⢸ ⡇ ⢸ ⡇ ⢸ ⡇ ⢸ ⠉⡏⠁ ⢸ ⡇ ⡇ ⡇ ⡇ ⢸ ⡇ 3.55▀
⢸ ⡇ ⢸ ⡇ ⢸ ⡇ ⢸ ⡇ ⢸ ⡇ ⡇ ⡇ ⡇ ⢸ ⡇ ▀
0 ⠘⠻⢦⣄⡀ ⡇ ⢸ ⡇ ⢸ ⡇ ⢸ ⡇ ⢸ ⡇ ⡇ ⡇ ⡇ ⢸ ⢀⡇ 1.775▘
⠈+⠳⠧⣖⣻⢀ ⡇ ⢸ ⡇ ⢸ ⡇ ⢸ ⡇ ⡇ ⡇ ⡇⣀⢸ ⣠⠤⠖⠚⠉ ▘
+⠛⠶⣤⣀ ⡇ ⣸ ⡇ ⢸ ⡇ ⢸ ⡇ ⡇ ⡇ ⢀⣠⠇⠈⠉⠉ 0
+⠛⠳⢯⣹⣠ ⡇ ⢸ ⡇ ⢸ ⡇ ⡇⠲⢤⣇⡤⠖⠚⠉
+⠙⠲⢤⣀⡀⡇ ⣸ ⡇ ⢸⡀ ⡇ ⢀⣀⡤⠴⠃
0 +⠙⠓⠯⣽⣠ ⡇ ⣸⠉⠓⠓⠋⠉
0.5 +⠉⠓⠦⣄⡀⡇⣀⡤⠴⠒⠋⠁
1 ⠉⠉⠁
1.5 Quarter
2
2.5 3
drag to rotate
Code
import { glyphChartBars3d, renderGlyphChart3d } from "@glyphcss/charts/3d";
const mark = glyphChartBars3d([
{
x: 0,
y: 0,
z: 4,
quarter: "Q1",
region: "EU"
},
{
x: 1,
y: 0,
z: 5.3,
quarter: "Q2",
region: "EU"
},
{
x: 2,
y: 0,
z: 6.1,
quarter: "Q3",
region: "EU"
},
{
x: 3,
y: 0,
z: 6.5,
quarter: "Q4",
region: "EU"
},
{
x: 0,
y: 1,
z: 5.7,
quarter: "Q1",
region: "US"
},
{
x: 1,
y: 1,
z: 6.5,
quarter: "Q2",
region: "US"
},
{
x: 2,
y: 1,
z: 6.9,
quarter: "Q3",
region: "US"
},
{
x: 3,
y: 1,
z: 7.1,
quarter: "Q4",
region: "US"
},
{
x: 0,
y: 2,
z: 3.9,
quarter: "Q1",
region: "APAC"
},
{
x: 1,
y: 2,
z: 4.3,
quarter: "Q2",
region: "APAC"
},
{
x: 2,
y: 2,
z: 4.5,
quarter: "Q3",
region: "APAC"
},
{
x: 3,
y: 2,
z: 5.2,
quarter: "Q4",
region: "APAC"
},
{
x: 0,
y: 3,
z: 2.9,
quarter: "Q1",
region: "LATAM"
},
{
x: 1,
y: 3,
z: 3.1,
quarter: "Q2",
region: "LATAM"
},
{
x: 2,
y: 3,
z: 3.8,
quarter: "Q3",
region: "LATAM"
},
{
x: 3,
y: 3,
z: 5,
quarter: "Q4",
region: "LATAM"
}
], {
xLabel: "quarter",
yLabel: "region"
}, {
axes: {
x: {
title: "Quarter"
},
y: {
title: "Region"
},
z: {
title: "Revenue",
ticks: 3
}
}
});
const { text } = renderGlyphChart3d(mark, {
target: "web",
width: 88,
height: 34,
charset: "braille"
});
console.log(text); glyphChartBars3d(records, channels?, options?) places bars at numeric x/y with z heights; xLabel/yLabel name them. barWidth defaults to 0.7.
⢀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⡀
z ⣀⣠⣤⣶⠾⠟⠛⠛⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠛⠛⠛⠷⠶⣦⣤⣄⣀⡀
⣴⡾⠟⠋⠁ ⠈⠉⠙⠛⠷⣦⣄⡀
⡄ ⠉⠛⠷⣦⣄
3.5 + ⣀⣠⣤⣤⣶⣶⣶⣶⠶⠶⠶⠶⠶⠶⢶⣤⣤⣤⣤⣀⣀⣀ ⠈⠛⢿⣦⡀
3 + ⣀⣤⣶⠿⠛⠋⠉ 1⠈⠉⠉⠙⠛⠻⠶⣶⣤⣤⣀ ⠈⠻⣦⡀
⡇ ⢠⣴⠿⠃⠉ ⠉⠙⠻⢶⣤⣀ ⣠⠘⣷
2.5 + ⡿ 0.5⣀⣀⡀ ⠈⠙⠻⣶⣤⡾⠋ ⢹
⡇ ⣷⡀ ⢀⣠0⣤⣶⠶⠶⠾⠛⠛⠛⠋⠉⠉⠛⠛⠛⠛⠛⠛⣛⠷⠶⣦⣤⣤y⣀⣀⡀ ⣀⣤⣾⠟⠋⠻⣦⡀⣼
2 + ⠉⠻⣶⣴⣾⡛⠋⠁ ⣀⡤⠴⠒⠋⠁+ ⠉⠉⠙⣻⣷⣶⣾⣟⡛⠉ ⢘⣿⣏
1.5 + -0.5 ⣰⡟⠁⠈⠙⠛⠿⢶⣤⣤⣄⣀⣀⣀⢀⣀⡤⠖⠚⠉⠁⢀⣀⣀⣀⣠⣤⣤⣤⣴⣶⠶⠟⠛⠋⠉⠁⠉⠛⢿⣷⣦⣀ ⣠⣾⠏⣿⡄
⡇ ⢸⣟ ⢈⣩⠉⠉⠛⠛⠛⠛+⠛⠛⠛⠛⠛⠛⠛⠛⠉⠉⠉ ⠈⣙⣿⣿⣟⠁ ⣼⡇
1 -1+ ⠈⢿⣦⣀⢀⣠⣤⡶⠿+⠉ ⣀⣠⣴⠾⠛⠉⠈⠻⣷⣄⣿
⡇ ⣀⣤⣽⠛⠿⣷⣥⣄⡀ ⢀⣀⣠⣤⡶⠟⠋⠉ ⢈⣿⠃
0.5 + ⢀⣀⡤⠖⠚⠉+⣾⠇ ⠈⠉⠛⠛⠿⠶⠶⢶⣦⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⡶⠶⠶⠶⠟⠛⠛⠉⠉ ⣠⣴⠟⠁⢿⡆
⢧⣖⠋⠉ ⠸⣷⡀ ⣠⣴⡾⠟⠁ ⣼⠇
0 +⠈⠙⠲⢤⣀ ⠙⠿⣦⣄ ⢀⣀⣠⣤⡶⠟⠋⠁ ⣰⡟
⠈⠙⠲⠤⣄⡀ ⠘⠻⠿⢶⣦⣤⣄⣀⡀ ⢀⣀⣠⣤⡶⠶⠟⠛⠉⠉ ⢀⣾⠟
+ ⠉⠓⠦⣄⡀ ⠉⠙⠛⠛⠛⠛⠛⠛⠷⠶⠶⠶⠾⠛⠛⠛⠛⠛⠛⠛⠉⠉ ⢀⣴⡿⠋
⠉⠓+⢤⣀ ⢠⣴⠾⠛⠉
-1 ⠈⠙⠲⢤⣀
⠈⠙+⠦⣄⡀
-0.5 ⠉⠓⠦⣄⡀
0 ⠉+
x
0.5
drag to rotate
Code
import { glyphChartLine3d, renderGlyphChart3d } from "@glyphcss/charts/3d";
const mark = glyphChartLine3d([
{
name: "Strand A",
points: [
[1, 0, 0],
[0.99, 0.17, 0.06],
[0.94, 0.33, 0.11],
[0.88, 0.48, 0.17],
[0.79, 0.62, 0.22],
[0.67, 0.74, 0.28],
[0.54, 0.84, 0.33],
[0.39, 0.92, 0.39],
[0.24, 0.97, 0.44],
[0.07, 1, 0.5],
[-0.1, 1, 0.56],
[-0.26, 0.97, 0.61],
[-0.42, 0.91, 0.67],
[-0.56, 0.83, 0.72],
[-0.69, 0.72, 0.78],
[-0.8, 0.6, 0.83],
[-0.89, 0.46, 0.89],
[-0.95, 0.3, 0.94],
[-0.99, 0.14, 1],
[-1, -0.03, 1.06],
[-0.98, -0.19, 1.11],
[-0.94, -0.35, 1.17],
[-0.87, -0.5, 1.22],
[-0.77, -0.64, 1.28],
[-0.65, -0.76, 1.33],
[-0.52, -0.85, 1.39],
[-0.37, -0.93, 1.44],
[-0.21, -0.98, 1.5],
[-0.05, -1, 1.56],
[0.12, -0.99, 1.61],
[0.28, -0.96, 1.67],
[0.44, -0.9, 1.72],
[0.58, -0.81, 1.78],
[0.71, -0.71, 1.83],
[0.82, -0.58, 1.89],
[0.9, -0.43, 1.94],
[0.96, -0.28, 2],
[0.99, -0.12, 2.06],
[1, 0.05, 2.11],
[0.98, 0.22, 2.17],
[0.93, 0.37, 2.22],
[0.85, 0.52, 2.28],
[0.75, 0.66, 2.33],
[0.63, 0.77, 2.39],
[0.5, 0.87, 2.44],
[0.35, 0.94, 2.5],
[0.19, 0.98, 2.56],
[0.02, 1, 2.61],
[-0.15, 0.99, 2.67],
[-0.31, 0.95, 2.72],
[-0.46, 0.89, 2.78],
[-0.6, 0.8, 2.83],
[-0.73, 0.69, 2.89],
[-0.83, 0.56, 2.94],
[-0.91, 0.41, 3],
[-0.97, 0.26, 3.06],
[-1, 0.09, 3.11],
[-1, -0.08, 3.17],
[-0.97, -0.24, 3.22],
[-0.92, -0.4, 3.28]
]
},
{
name: "Strand B",
points: [
[-1, 0, 0],
[-0.99, -0.17, 0.06],
[-0.94, -0.33, 0.11],
[-0.88, -0.48, 0.17],
[-0.79, -0.62, 0.22],
[-0.67, -0.74, 0.28],
[-0.54, -0.84, 0.33],
[-0.39, -0.92, 0.39],
[-0.24, -0.97, 0.44],
[-0.07, -1, 0.5],
[0.1, -1, 0.56],
[0.26, -0.97, 0.61],
[0.42, -0.91, 0.67],
[0.56, -0.83, 0.72],
[0.69, -0.72, 0.78],
[0.8, -0.6, 0.83],
[0.89, -0.46, 0.89],
[0.95, -0.3, 0.94],
[0.99, -0.14, 1],
[1, 0.03, 1.06],
[0.98, 0.19, 1.11],
[0.94, 0.35, 1.17],
[0.87, 0.5, 1.22],
[0.77, 0.64, 1.28],
[0.65, 0.76, 1.33],
[0.52, 0.85, 1.39],
[0.37, 0.93, 1.44],
[0.21, 0.98, 1.5],
[0.05, 1, 1.56],
[-0.12, 0.99, 1.61],
[-0.28, 0.96, 1.67],
[-0.44, 0.9, 1.72],
[-0.58, 0.81, 1.78],
[-0.71, 0.71, 1.83],
[-0.82, 0.58, 1.89],
[-0.9, 0.43, 1.94],
[-0.96, 0.28, 2],
[-0.99, 0.12, 2.06],
[-1, -0.05, 2.11],
[-0.98, -0.22, 2.17],
[-0.93, -0.37, 2.22],
[-0.85, -0.52, 2.28],
[-0.75, -0.66, 2.33],
[-0.63, -0.77, 2.39],
[-0.5, -0.87, 2.44],
[-0.35, -0.94, 2.5],
[-0.19, -0.98, 2.56],
[-0.02, -1, 2.61],
[0.15, -0.99, 2.67],
[0.31, -0.95, 2.72],
[0.46, -0.89, 2.78],
[0.6, -0.8, 2.83],
[0.73, -0.69, 2.89],
[0.83, -0.56, 2.94],
[0.91, -0.41, 3],
[0.97, -0.26, 3.06],
[1, -0.09, 3.11],
[1, 0.08, 3.17],
[0.97, 0.24, 3.22],
[0.92, 0.4, 3.28]
]
}
]);
const { text } = renderGlyphChart3d(mark, {
target: "web",
width: 88,
height: 34,
charset: "braille"
});
console.log(text); glyphChartLine3d(points, options?) takes [x, y, z] triples or named series { name, color, points }. glyphChart3dLorenzAttractor() generates a long trajectory.
Render options
Section titled “Render options”| Option | Values |
|---|---|
charset | braille (draws wireframe), blocks, box, ascii (draw solid) |
style | solid, wireframe, ink |
camera | { rotX, rotY } in degrees, optional zoom, or a mat matrix; default { rotX: 69, rotY: 318 } |
colorscale (mark option) | viridis, cividis, magma, greys, or hex anchors |
The result carries text, CSS html, resolved.camera (pass it back to reproduce a frame) and report.
Interactive scene
Section titled “Interactive scene”import { createGlyphScene, createGlyphOrthographicCamera } from "glyphcss";import { glyphChartSurface, glyphChartObject } from "@glyphcss/charts/3d";
const camera = createGlyphOrthographicCamera({ rotX: 69, rotY: 318, zoom: 100 });const scene = createGlyphScene(host, { camera, cols: 80, rows: 30, mode: "solid" });scene.addObject(glyphChartObject(glyphChartSurface({ z: [[0, 1], [1, 2]] })));scene.rerender();glyphChartObject mounts any mark in a live scene; add controls to orbit it. The chart CLI renders surfaces with --3d.