Draw a cuboid

From Rosetta Code
Task
Draw a cuboid
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Draw a   cuboid   with relative dimensions of   2 × 3 × 4.


The cuboid can be represented graphically, or in   ASCII art,   depending on the language capabilities.

To fulfill the criteria of being a cuboid, three faces must be visible.

Either static or rotational projection is acceptable for this task.


Related tasks



11l

Translation of: Nim

<lang 11l>F cline(n, x, y, cde)

  print(String(cde[0]).rjust(n + 1)‘’
              (cde[1] * (9 * x - 1))‘’
              cde[0]‘’
              (I cde.len > 2 {String(cde[2]).rjust(y + 1)} E ‘’))

F cuboid(x, y, z)

  cline(y + 1, x, 0, ‘+-’)
  L(i) 1 .. y
     cline(y - i + 1, x, i - 1, ‘/ |’)
  cline(0, x, y, ‘+-|’)
  L 0 .. 4 * z - y - 3
     cline(0, x, y, ‘| |’)
  cline(0, x, y, ‘| +’)
  L(i) (y - 1 .. 0).step(-1)
     cline(0, x, i, ‘| /’)
  cline(0, x, 0, "+-\n")

cuboid(2, 3, 4) cuboid(1, 1, 1) cuboid(6, 2, 1)</lang>

Output:
    +-----------------+
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

  +--------+
 /        /|
+--------+ |
|        | |
|        | +
|        |/
+--------+

   +-----------------------------------------------------+
  /                                                     /|
 /                                                     / |
+-----------------------------------------------------+  |
|                                                     |  +
|                                                     | /
|                                                     |/
+-----------------------------------------------------+

Action!

<lang Action!>PROC DrawCuboid(CARD x,y BYTE w,h,d)

 BYTE wsize=[10],hsize=[10],dsize=[5]
 BYTE i
 FOR i=0 TO w
 DO
   Plot(x+i*wsize,y+h*hsize)
   DrawTo(x+i*wsize,y)
   DrawTo(x+i*wsize+d*dsize,y-d*dsize)
 OD
 FOR i=0 TO h
 DO
   Plot(x,y+i*hsize)
   DrawTo(x+w*wsize,y+i*hsize)
   DrawTo(x+w*wsize+d*dsize,y+i*hsize-d*dsize)
 OD
 FOR i=1 TO d
 DO
   Plot(x+i*dsize,y-i*dsize)
   DrawTo(x+w*wsize+i*dsize,y-i*dsize)
   DrawTo(x+w*wsize+i*dsize,y+h*hsize-i*dsize)
 OD

RETURN

PROC Main()

 BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6
 
 Graphics(8+16)
 COLOR1=$0C
 COLOR2=$02
 Color=1
 DrawCuboid(60,45,2,3,4)
 DrawCuboid(130,40,2,4,3)
 DrawCuboid(205,50,3,2,4)
 DrawCuboid(55,120,3,4,2)
 DrawCuboid(120,130,4,2,3)
 DrawCuboid(200,125,4,3,2)
 DO UNTIL CH#$FF OD
 CH=$FF

RETURN</lang>

Output:

Screenshot from Atari 8-bit computer

Ada

ASCII-Art output, one width unit is two characters long ('--'). <lang Ada>with Ada.Text_IO;

procedure Main is

  type Char_Matrix is
    array (Positive range <>, Positive range <>) of Character;
  function Create_Cuboid
    (Width, Height, Depth : Positive)
     return                 Char_Matrix
  is
     Result : Char_Matrix (1 .. Height + Depth + 3,
        1 .. 2 * Width + Depth + 3) := (others => (others => ' '));
  begin
     -- points
     Result (1, 1)                                      := '+';
     Result (Height + 2, 1)                             := '+';
     Result (1, 2 * Width + 2)                          := '+';
     Result (Height + 2, 2 * Width + 2)                 := '+';
     Result (Height + Depth + 3, Depth + 2)             := '+';
     Result (Depth + 2, 2 * Width + Depth + 3)          := '+';
     Result (Height + Depth + 3, 2 * Width + Depth + 3) := '+';
     -- width lines
     for I in 1 .. 2 * Width loop
        Result (1, I + 1)                          := '-';
        Result (Height + 2, I + 1)                 := '-';
        Result (Height + Depth + 3, Depth + I + 2) := '-';
     end loop;
     -- height lines
     for I in 1 .. Height loop
        Result (I + 1, 1)                             := '|';
        Result (I + 1, 2 * Width + 2)                 := '|';
        Result (Depth + I + 2, 2 * Width + Depth + 3) := '|';
     end loop;
     -- depth lines
     for I in 1 .. Depth loop
        Result (Height + 2 + I, 1 + I)             := '/';
        Result (1 + I, 2 * Width + 2 + I)          := '/';
        Result (Height + 2 + I, 2 * Width + 2 + I) := '/';
     end loop;
     return Result;
  end Create_Cuboid;
  procedure Print_Cuboid (Width, Height, Depth : Positive) is
     Cuboid : Char_Matrix := Create_Cuboid (Width, Height, Depth);
  begin
     for Row in reverse Cuboid'Range (1) loop
        for Col in Cuboid'Range (2) loop
           Ada.Text_IO.Put (Cuboid (Row, Col));
        end loop;
        Ada.Text_IO.New_Line;
     end loop;
  end Print_Cuboid;

begin

  Print_Cuboid (2, 3, 4);

end Main;</lang>

Output:
     +----+
    /    /|
   /    / |
  /    /  |
 /    /   +
+----+   / 
|    |  /  
|    | /   
|    |/    
+----+     

Arturo

Translation of: PicoLisp

<lang rebol>cline: function [n,a,b,cde][

   print (pad to :string first cde n+1) ++
         (repeat to :string cde\1 dec 9*a)++
         (to :string cde\0)++
         (2 < size cde)? -> pad to :string cde\2 b+1 -> ""

]

cuboid: function [x,y,z][

   cline y+1 x 0 "+-"
   loop 1..y 'i -> cline 1+y-i x i-1 "/ |"
   cline 0 x y "+-|"
   loop 0..((4*z)-y)-3 'i -> cline 0 x y "| |"
   cline 0 x y "| +"
   loop (y-1)..0 'i -> cline 0 x i "| /"
   cline 0 x 0 "+-\n"

]

cuboid 2 3 4 cuboid 1 1 1 cuboid 6 2 1</lang>

Output:
    +-----------------+
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

  +--------+
 /        /|
+--------+ |
|        | |
|        | +
|        |/
+--------+

   +-----------------------------------------------------+
  /                                                     /|
 /                                                     / |
+-----------------------------------------------------+  |
|                                                     |  |
|                                                     |  |
|                                                     |  +
|                                                     | /
|                                                     |/
+-----------------------------------------------------+

AutoHotkey

Library: GDIP

Some portions of code from Gdip examples.

<lang AutoHotkey>Angle := 45 C := 0.01745329252 W := 200 H := 300 L := 400 LX := L * Cos(Angle * C), LY := L * Sin(Angle * C)

If !pToken := Gdip_Startup() {

  MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
  ExitApp

} OnExit, Exit

A := 50, B := 650, WinWidth := 700, WinHeight := 700 TopX := (A_ScreenWidth - WinWidth) //2, TopY := (A_ScreenHeight - WinHeight) //2

Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs Gui, 1: Show, NA hwnd1 := WinExist(), hbm := CreateDIBSection(WinWidth, WinHeight), hdc := CreateCompatibleDC() , obm := SelectObject(hdc, hbm), G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)

Points := A "," B "|" A+W "," B "|" A+W "," B-H "|" A "," B-H , DrawFace(Points, 0xff0066ff, G)

Points := A+W "," B "|" A+W+LX "," B-LY "|" A+W+LX "," B-LY-H "|" A+W "," B-H , DrawFace(Points, 0xff00d400, G)

Points := A "," B-H "|" A+W "," B-H "|" A+W+LX "," B-LY-H "|" A+LX "," B-LY-H , DrawFace(Points, 0xffd40055, G)

UpdateLayeredWindow(hwnd1, hdc, TopX, TopY, WinWidth, WinHeight)

SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc) , Gdip_DeleteGraphics(G) return

DrawFace(Points, Color, G) { pBrush := Gdip_BrushCreateSolid(Color) , Gdip_FillPolygon(G, pBrush, Points, 1) , Gdip_DeleteBrush(pBrush) return }

Esc:: Exit: Gdip_Shutdown(pToken) ExitApp</lang>

AWK

<lang AWK>

  1. syntax: GAWK -f DRAW_A_CUBOID.AWK [-v x=?] [-v y=?] [-v z=?]
  2. example: GAWK -f DRAW_A_CUBOID.AWK -v x=12 -v y=4 -v z=6
  3. converted from VBSCRIPT

BEGIN {

   init_sides()
   draw_cuboid(2,3,4)
   draw_cuboid(1,1,1)
   draw_cuboid(6,2,1)
   exit (errors == 0) ? 0 : 1

} function draw_cuboid(nx,ny,nz, esf,i,i_max,j,j_max,lx,ly,lz) {

   esf = errors # errors so far
   if (nx !~ /^[0-9]+$/ || nx <= 0) { error(nx,ny,nz,1) }
   if (ny !~ /^[0-9]+$/ || ny <= 0) { error(nx,ny,nz,2) }
   if (nz !~ /^[0-9]+$/ || nz <= 0) { error(nx,ny,nz,3) }
   if (errors > esf) { return }
   lx = x * nx
   ly = y * ny
   lz = z * nz
  1. define the array size
   i_max = ly + lz
   j_max = lx + ly
   delete arr
   printf("%s %s %s (%d rows x %d columns)\n",nx,ny,nz,i_max+1,j_max+1)
  1. draw lines
   for (i=0; i<=nz-1; i++) { draw_line(lx,0,z*i,"-") }
   for (i=0; i<=ny; i++)   { draw_line(lx,y*i,lz+y*i,"-") }
   for (i=0; i<=nx-1; i++) { draw_line(lz,x*i,0,"|") }
   for (i=0; i<=ny; i++)   { draw_line(lz,lx+y*i,y*i,"|") }
   for (i=0; i<=nz-1; i++) { draw_line(ly,lx,z*i,"/") }
   for (i=0; i<=nx; i++)   { draw_line(ly,x*i,lz,"/") }
  1. output the cuboid
   for (i=i_max; i>=0; i--) {
     for (j=0; j<=j_max; j++) {
       printf("%1s",arr[i,j])
     }
     printf("\n")
   }

} function draw_line(n,x,y,c, dx,dy,i,xi,yi) {

   if      (c == "-") { dx = 1 ; dy = 0 }
   else if (c == "|") { dx = 0 ; dy = 1 }
   else if (c == "/") { dx = 1 ; dy = 1 }
   for (i=0; i<=n; i++) {
     xi = x + i * dx
     yi = y + i * dy
     arr[yi,xi] = (arr[yi,xi] ~ /^ ?$/) ? c : "+"
   }

} function error(x,y,z,arg) {

   printf("error: '%s,%s,%s' argument %d is invalid\n",x,y,z,arg)
   errors++

} function init_sides() {

  1. to change the defaults on the command line use: -v x=? -v y=? -v z=?
   if (x+0 < 2) { x = 6 } # top
   if (y+0 < 2) { y = 2 } # right
   if (z+0 < 2) { z = 3 } # front

} </lang>

Output:
2 3 4 (19 rows x 19 columns)
      +-----+-----+
     /     /     /|
    +-----+-----+ |
   /     /     /| +
  +-----+-----+ |/|
 /     /     /| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/
|     |     |/| +
+-----+-----+ |/
|     |     | +
|     |     |/
+-----+-----+
1 1 1 (6 rows x 9 columns)
  +-----+
 /     /|
+-----+ |
|     | +
|     |/
+-----+
6 2 1 (8 rows x 41 columns)
    +-----+-----+-----+-----+-----+-----+
   /     /     /     /     /     /     /|
  +-----+-----+-----+-----+-----+-----+ |
 /     /     /     /     /     /     /| +
+-----+-----+-----+-----+-----+-----+ |/
|     |     |     |     |     |     | +
|     |     |     |     |     |     |/
+-----+-----+-----+-----+-----+-----+

BBC BASIC

Uses BBC BASIC's native parallelogram plot. <lang bbcbasic> ORIGIN 100, 100

     PROCcuboid(200, 300, 400)
     END
     
     DEF PROCcuboid(x, y, z)
     MOVE 0, 0 : MOVE 0, y
     GCOL 1 : PLOT 117, x, y
     GCOL 2 : PLOT 117, x + z * 0.4, y + z * 0.4
     GCOL 4 : PLOT 117, x + z * 0.4, z * 0.4
     ENDPROC

</lang>

Output:

Befunge

Given a width, height, and depth, this produces an approximate isometric representation of the shape using ASCII art.

<lang befunge>" :htdiW">:#,_>&>00p" :thgieH">:#,_>&>:10p0" :htpeD">:#,_$>&>:20p55+,+:1`*:vv v\-*`0:-g01\++*`\0:-\-1g01:\-*`0:-g02\+*`\0:-\-1g02<:::::<\g3`\g01:\1\+55\1-1_v >":"\1\:20g\`!3g:30p\00g2*\::20g\`\20g1-\`+1+3g\1\30g\:20g-::0\`\2*1+*-\48*\:^v /\_ @_\#!:!#$>#$_\#!:,#-\#1 <+1\<*84g02"_"+1*2g00+551$<</lang>

Output:
Width:  2
Height: 3
Depth:  4

    _____
   /    /\
  /    /::\
 /    /::::\
/____/:::::/
\\\\\\::::/
 \\\\\\::/
  \\\\\\/

Brlcad

In brlcad, we use the rpp (rectangular parallelepiped) primitive to create the cuboid. This defines the cuboid area using the parameters xmin,xmax,ymin,ymax,zmin,zmax

<lang brlcad>opendb cuboid.g y # Create a database to hold our shapes units cm # Set the unit of measure in cuboid.s rpp 0 2 0 3 0 4 # Create a 2 x 3 x 4 cuboid named cuboid.s</lang>

C

Code works fine but only '.' and ':' characters show up on the cuboid. <lang c>

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <math.h>

const char *shades = ".:!*oe&#%@";

void vsub(double *v1, double *v2, double *s) { s[0] = v1[0] - v2[0]; s[1] = v1[1] - v2[1]; s[2] = v1[2] - v2[2]; }

double normalize(double * v) {

       double len = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
       v[0] /= len; v[1] /= len; v[2] /= len;

return len; }

double dot(double *x, double *y) {

       return x[0]*y[0] + x[1]*y[1] + x[2]*y[2];

}

double * cross(double x[3], double y[3], double s[3]) { s[0] = x[1] * y[2] - x[2] * y[1]; s[1] = x[2] * y[0] - x[0] * y[2]; s[2] = x[0] * y[1] - x[1] * y[0]; return s; }

double* madd(double *x, double *y, double d, double *r) { r[0] = x[0] + y[0] * d; r[1] = x[1] + y[1] * d; r[2] = x[2] + y[2] * d; return r; }

double v000[] = { -4, -3, -2 }; double v100[] = { 4, -3, -2 }; double v010[] = { -4, 3, -2 }; double v110[] = { 4, 3, -2 }; double v001[] = { -4, -3, 2 }; double v101[] = { 4, -3, 2 }; double v011[] = { -4, 3, 2 }; double v111[] = { 4, 3, 2 };

typedef struct { double * v[4]; double norm[3]; } face_t;

face_t f[] = { { { v000, v010, v110, v100 }, { 0, 0, -1 } }, { { v001, v011, v111, v101 }, { 0, 0, 1 } }, { { v000, v010, v011, v001 }, { -1, 0, 0 } }, { { v100, v110, v111, v101 }, { 1, 0, 0 } }, { { v000, v100, v101, v001 }, { 0, -1, 0 } }, { { v010, v110, v111, v011 }, { 0, 1, 0 } }, };

int in_range(double x, double x0, double x1) { return (x - x0) * (x - x1) <= 0; }

int face_hit(face_t *face, double src[3], double dir[3], double hit[3], double *d) { int i; double dist; for (i = 0; i < 3; i++) if (face->norm[i]) dist = (face->v[0][i] - src[i]) / dir[i];

madd(src, dir, dist, hit); *d = fabs(dot(dir, face->norm) * dist);

if (face->norm[0]) { return in_range(hit[1], face->v[0][1], face->v[2][1]) && in_range(hit[2], face->v[0][2], face->v[2][2]); } else if (face->norm[1]) { return in_range(hit[0], face->v[0][0], face->v[2][0]) && in_range(hit[2], face->v[0][2], face->v[2][2]); } else if (face->norm[2]) { return in_range(hit[0], face->v[0][0], face->v[2][0]) && in_range(hit[1], face->v[0][1], face->v[2][1]); } return 0; }

int main() { int i, j, k; double eye[3] = { 7, 7, 6 }; double dir[3] = { -1, -1, -1 }, orig[3] = {0, 0, 0}; double hit[3], dx[3], dy[3] = {0, 0, 1}, proj[3]; double d, *norm, dbest, b; double light[3] = { 6, 8, 6 }, ldist[3], decay, strength = 10;

	normalize(cross(eye, dy, dx));

normalize(cross(eye, dx, dy));

for (i = -10; i <= 17; i++) { for (j = -35; j < 35; j++) { vsub(orig, orig, proj); madd(madd(proj, dx, j / 6., proj), dy, i/3., proj); vsub(proj, eye, dir); dbest = 1e100; norm = 0; for (k = 0; k < 6; k++) { if (!face_hit(f + k, eye, dir, hit, &d)) continue; if (dbest > d) { dbest = d; norm = f[k].norm; } }

if (!norm) { putchar(' '); continue; }

vsub(light, hit, ldist); decay = normalize(ldist); b = dot(norm, ldist) / decay * strength; if (b < 0) b = 0; else if (b > 1) b = 1; b += .2; if (b > 1) b = 0; else b = 1 - b; putchar(shades[(int)(b * (sizeof(shades) - 2))]); } putchar('\n'); }

       return 0;

}</lang>

Output :

                                
                                .
                        ................
                ...............................
         .............................................
     ........................................................
     ...............................................................
      ..............................................................::
      ...........................................................::::
       .......................................................:::::::
       .....................................................::::::::
        .................................................::::::::::
        :..............................................::::::::::::
         :............................................::::::::::::
         ::..........................................:::::::::::::
           :........................................:::::::::::::
             ......................................::::::::::::::
               ....................................:::::::::::::
                 .................................::::::::::::
                    ............................::::::::::::
                      .........................:::::::::::
                        ......................::::::::::
                          ...................:::::::::
                             ..............:::::::::
                               ...........:::::::::
                                 .........:::::::
                                   .......:::::
                                     .....:::
                                        .::

C#

Translation of: Java

<lang csharp>using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;

namespace Cuboid {

   public partial class Form1 : Form
   {
       double[][] nodes = {
           new double[] {-1, -1, -1}, new double[] {-1, -1, 1}, new double[] {-1, 1, -1},
           new double[] {-1, 1, 1}, new double[] {1, -1, -1}, new double[] {1, -1, 1},
           new double[] {1, 1, -1}, new double[] {1, 1, 1} };
       int[][] edges = {
           new int[] {0, 1}, new int[] {1, 3}, new int[] {3, 2}, new int[] {2, 0}, new int[] {4, 5},
           new int[] {5, 7}, new int[] {7, 6}, new int[] {6, 4}, new int[] {0, 4}, new int[] {1, 5},
           new int[] {2, 6}, new int[] {3, 7}};
       private int mouseX;
       private int prevMouseX;
       private int prevMouseY;
       private int mouseY;
       public Form1()
       {
           Width = Height = 640;
           StartPosition = FormStartPosition.CenterScreen;
           SetStyle(
               ControlStyles.AllPaintingInWmPaint |
               ControlStyles.UserPaint |
               ControlStyles.DoubleBuffer,
               true);
           MouseMove += (s, e) =>
           {
               prevMouseX = mouseX;
               prevMouseY = mouseY;
               mouseX = e.X;
               mouseY = e.Y;
               double incrX = (mouseX - prevMouseX) * 0.01;
               double incrY = (mouseY - prevMouseY) * 0.01;
               RotateCuboid(incrX, incrY);
               Refresh();
           };
           MouseDown += (s, e) =>
           {
               mouseX = e.X;
               mouseY = e.Y;
           };
           Scale(80, 120, 160);
           RotateCuboid(Math.PI / 5, Math.PI / 9);
       }
       private void RotateCuboid(double angleX, double angleY)
       {
           double sinX = Math.Sin(angleX);
           double cosX = Math.Cos(angleX);
           double sinY = Math.Sin(angleY);
           double cosY = Math.Cos(angleY);
           foreach (var node in nodes)
           {
               double x = node[0];
               double y = node[1];
               double z = node[2];
               node[0] = x * cosX - z * sinX;
               node[2] = z * cosX + x * sinX;
               z = node[2];
               node[1] = y * cosY - z * sinY;
               node[2] = z * cosY + y * sinY;
           }
       }
       private void Scale(int v1, int v2, int v3)
       {
           foreach (var item in nodes)
           {
               item[0] *= v1;
               item[1] *= v2;
               item[2] *= v3;
           }
       }
       protected override void OnPaint(PaintEventArgs args)
       {
           var g = args.Graphics;
           g.SmoothingMode = SmoothingMode.HighQuality;
           g.Clear(Color.White);
           g.TranslateTransform(Width / 2, Height / 2);
           foreach (var edge in edges)
           {
               double[] xy1 = nodes[edge[0]];
               double[] xy2 = nodes[edge[1]];
               g.DrawLine(Pens.Black, (int)Math.Round(xy1[0]), (int)Math.Round(xy1[1]),
                       (int)Math.Round(xy2[0]), (int)Math.Round(xy2[1]));
           }
           foreach (var node in nodes)
           {
               g.FillEllipse(Brushes.Black, (int)Math.Round(node[0]) - 4,
                   (int)Math.Round(node[1]) - 4, 8, 8);
           }
       }
   }

}</lang>

C++

This code needs the BGI for Windows available at Colorado State University.

<lang cpp>

  1. include<graphics.h>
  2. include<iostream>

int main() {

   int k;
   initwindow(1500,810,"Rosetta Cuboid");
   
   do{
      std::cout<<"Enter ratio of sides ( 0 or -ve to exit) : ";
      std::cin>>k;
      
      if(k>0){
               bar3d(100, 100, 100 + 2*k, 100 + 4*k, 3*k, 1);
      }
      }while(k>0);
   
   return 0;

}

</lang>

Clojure

Library: quil

<lang clojure> (use 'quil.core)

(def w 500) (def h 400)

(defn setup []

 (background 0))

(defn draw []

 (push-matrix)
 (translate (/ w 2) (/ h 2) 0)
 (rotate-x 0.7)
 (rotate-z 0.5)
 (box 100 150 200)  ; 2x3x4 relative dimensions
 (pop-matrix))

(defsketch main

 :title "cuboid"
 :setup setup
 :size [w h]
 :draw draw
 :renderer :opengl)

</lang>

Output:

[1]

D

Translation of: Go

<lang d>import std.stdio, std.array;

void printCuboid(in int dx, in int dy, in int dz) {

   static cline(in int n, in int dx, in int dy, in string cde) {
       writef("%*s", n+1, cde[0 .. 1]);
       write(cde[1 .. 2].replicate(9*dx - 1));
       write(cde[0]);
       writefln("%*s", dy+1, cde[2 .. $]);
   }
   cline(dy+1, dx, 0, "+-");
   foreach (i; 1 .. dy+1)
       cline(dy-i+1, dx, i-1, "/ |");
   cline(0, dx, dy, "+-|");
   foreach (_; 0 .. 4*dz - dy - 2)
       cline(0, dx, dy, "| |");
   cline(0, dx, dy, "| +");
   foreach_reverse (i; 0 .. dy)
       cline(0, dx, i, "| /");
   cline(0, dx, 0, "+-\n");

}

void main() {

   printCuboid(2, 3, 4);
   printCuboid(1, 1, 1);
   printCuboid(6, 2, 1);

}</lang>

Output:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

  +--------+ 
 /        /|
+--------+ |
|        | |
|        | +
|        |/
+--------+

   +-----------------------------------------------------+ 
  /                                                     /|
 /                                                     / |
+-----------------------------------------------------+  |
|                                                     |  +
|                                                     | /
|                                                     |/
+-----------------------------------------------------+

Delphi

Translation of: Go

<lang Delphi> program Draw_a_cuboid;

{$APPTYPE CONSOLE}

uses

 System.SysUtils;

procedure cubLine(n, dx, dy: Integer; cde: string); var

 i: integer;

begin

 write(format('%' + (n + 1).ToString + 's', [cde.Substring(0, 1)]));
 for i := 9 * dx - 1 downto 1 do
   Write(cde.Substring(1, 1));
 Write(cde.Substring(0, 1));
 Writeln(cde.Substring(2, cde.Length).PadLeft(dy + 1));

end;

procedure cuboid(dx, dy, dz: integer); var

 i: integer;

begin

 Writeln(Format('cuboid %d %d %d:', [dx, dy, dz]));
 cubLine(dy + 1, dx, 0, '+-');
 for i := 1 to dy do
   cubLine(dy - i + 1, dx, i - 1, '/ |');
 cubLine(0, dx, dy, '+-|');
 for i := 4 * dz - dy - 2 downto 1 do
   cubLine(0, dx, dy, '| |');
 cubLine(0, dx, dy, '| +');
 for i := 1 to dy do
   cubLine(0, dx, dy - i, '| /');
 cubLine(0, dx, 0, '+-');
 Writeln;

end;

begin

 cuboid(2, 3, 4);
 cuboid(1, 1, 1);
 cuboid(6, 2, 1);
 readln;

end.</lang>

Elixir

Translation of: Ruby

<lang elixir>defmodule Cuboid do

 @x 6
 @y 2
 @z 3
 @dir %{-: {1,0}, |: {0,1}, /: {1,1}}
 
 def draw(nx, ny, nz) do
   IO.puts "cuboid #{nx} #{ny} #{nz}:"
   {x, y, z} = {@x*nx, @y*ny, @z*nz}
   area = Map.new
   area = Enum.reduce(0..nz-1, area, fn i,acc -> draw_line(acc, x,      0,   @z*i, :-) end)
   area = Enum.reduce(0..ny,   area, fn i,acc -> draw_line(acc, x,   @y*i, z+@y*i, :-) end)
   area = Enum.reduce(0..nx-1, area, fn i,acc -> draw_line(acc, z,   @x*i,      0, :|) end)
   area = Enum.reduce(0..ny,   area, fn i,acc -> draw_line(acc, z, x+@y*i,   @y*i, :|) end)
   area = Enum.reduce(0..nz-1, area, fn i,acc -> draw_line(acc, y,      x,   @z*i, :/) end)
   area = Enum.reduce(0..nx,   area, fn i,acc -> draw_line(acc, y,   @x*i,      z, :/) end)
   Enum.each(y+z..0, fn j ->
     IO.puts Enum.map_join(0..x+y, fn i -> Map.get(area, {i,j}, " ") end)
   end)
 end
 
 defp draw_line(area, n, sx, sy, c) do
   {dx, dy} = Map.get(@dir, c)
   draw_line(area, n, sx, sy, c, dx, dy)
 end
 
 defp draw_line(area, n, _, _, _, _, _) when n<0, do: area
 defp draw_line(area, n, i, j, c, dx, dy) do
   Map.update(area, {i,j}, c, fn _ -> :+ end)
   |> draw_line(n-1, i+dx, j+dy, c, dx, dy)
 end

end

Cuboid.draw(2,3,4) Cuboid.draw(1,1,1) Cuboid.draw(2,4,1) Cuboid.draw(4,2,1)</lang>

Output:
cuboid 2 3 4:
      +-----+-----+
     /     /     /|
    +-----+-----+ |
   /     /     /| +
  +-----+-----+ |/|
 /     /     /| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/
|     |     |/| +
+-----+-----+ |/
|     |     | +
|     |     |/
+-----+-----+
cuboid 1 1 1:
  +-----+
 /     /|
+-----+ |
|     | +
|     |/
+-----+
cuboid 2 4 1:
        +-----+-----+
       /     /     /|
      +-----+-----+ |
     /     /     /| +
    +-----+-----+ |/
   /     /     /| +
  +-----+-----+ |/
 /     /     /| +
+-----+-----+ |/
|     |     | +
|     |     |/
+-----+-----+
cuboid 4 2 1:
    +-----+-----+-----+-----+
   /     /     /     /     /|
  +-----+-----+-----+-----+ |
 /     /     /     /     /| +
+-----+-----+-----+-----+ |/
|     |     |     |     | +
|     |     |     |     |/
+-----+-----+-----+-----+

Factor

Library: raylib
Works with: Factor version 0.99 development release 2019-07-10

<lang factor>USING: classes.struct kernel raylib.ffi ;

640 480 "cuboid" init-window

S{ Camera3D

   { position S{ Vector3 f 4.5 4.5 4.5 } }
   { target S{ Vector3 f 0 0 0 } }
   { up S{ Vector3 f 0 1 0 } }
   { fovy 45.0 }
   { type 0 }

}

60 set-target-fps

[ window-should-close ] [

   begin-drawing
       BLACK clear-background dup
       begin-mode-3d
           S{ Vector3 f 0 0 0 } 2 3 4 LIME draw-cube-wires
       end-mode-3d
   end-drawing

] until drop close-window</lang>

Output:

[2]

FreeBASIC

Adapted from OpenGL code that comes with FreeBASIC distributions.

<lang freebasic>#include once "GL/gl.bi"

  1. include once "GL/glu.bi"

dim rquad as single

screen 18, 16, , 2

glViewport 0, 0, 640, 480 Reset The Current Viewport glMatrixMode GL_PROJECTION Select The Projection Matrix glLoadIdentity Reset The Projection Matrix gluPerspective 45.0, 640.0/480.0, 0.1, 100.0 Calculate The Aspect Ratio Of The Window glMatrixMode GL_MODELVIEW Select The Modelview Matrix glLoadIdentity Reset The Modelview Matrix glShadeModel GL_SMOOTH Enable Smooth Shading glClearColor 0.0, 0.0, 0.0, 0.5 Black Background glClearDepth 1.0 Depth Buffer Setup glEnable GL_DEPTH_TEST Enables Depth Testing glDepthFunc GL_LEQUAL The Type Of Depth Testing To Do glHint GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST Really Nice Perspective Calculations do glClear GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT Clear Screen And Depth Buffer glLoadIdentity Reset The Current Modelview Matrix

glLoadIdentity Reset The Current Modelview Matrix glTranslatef 0.0, 0.0, -7.0 Move Right 1.5 Into The Screen 7.0 glRotatef rquad,1.0, 1.0, 1.0 Rotate The Quad On The X axis ( NEW )

glBegin GL_QUADS Draw A Quad

   glColor3f 0.0, 1.0, 0.0                               Set The Color To Blue
   glVertex3f 1.0, 1.5, -2.0                             Top Right Of The Quad (Top)
   glVertex3f -1.0, 1.5, -2.0                            Top Left Of The Quad (Top)
   glVertex3f -1.0, 1.5, 2.0                             Bottom Left Of The Quad (Top)
   glVertex3f 1.0, 1.5, 2.0                              Bottom Right Of The Quad (Top)
   glColor3f 1.0, 0.5, 0.0                               Set The Color To Orange
   glVertex3f 1.0, -1.5, 2.0                             Top Right Of The Quad (Bottom)
   glVertex3f -1.0, -1.5, 2.0                            Top Left Of The Quad (Bottom)
   glVertex3f -1.0, -1.5, -2.0                           Bottom Left Of The Quad (Bottom)
   glVertex3f 1.0, -1.5, -2.0                            Bottom Right Of The Quad (Bottom)
   glColor3f 1.0, 0.0, 0.0                               Set The Color To Red
   glVertex3f 1.0, 1.5, 2.0                              Top Right Of The Quad (Front)
   glVertex3f -1.0, 1.5, 2.0                             Top Left Of The Quad (Front)
   glVertex3f -1.0, -1.5, 2.0                            Bottom Left Of The Quad (Front)
   glVertex3f 1.0, -1.5, 2.0                             Bottom Right Of The Quad (Front)
   glColor3f 1.0, 1.0, 0.0                               Set The Color To Yellow
   glVertex3f 1.0, -1.5, -2.0                            Top Right Of The Quad (Back)
   glVertex3f -1.0, -1.5, -2.0                           Top Left Of The Quad (Back)
   glVertex3f -1.0, 1.5, -2.0                            Bottom Left Of The Quad (Back)
   glVertex3f 1.0, 1.5, -2.0                             Bottom Right Of The Quad (Back)
   glColor3f 0.0, 0.0, 1.0                               Set The Color To Blue
   glVertex3f -1.0, 1.5, 2.0                             Top Right Of The Quad (Left)
   glVertex3f -1.0, 1.5, -2.0                            Top Left Of The Quad (Left)
   glVertex3f -1.0, -1.5, -2.0                           Bottom Left Of The Quad (Left)
   glVertex3f -1.0, -1.5, 2.0                            Bottom Right Of The Quad (Left)
   glColor3f 1.0, 0.0, 1.0                               Set The Color To Violet
   glVertex3f 1.0, 1.5, -2.0                             Top Right Of The Quad (Right)
   glVertex3f 1.0, 1.5, 2.0                              Top Left Of The Quad (Right)
   glVertex3f 1.0, -1.5, 2.0                             Bottom Left Of The Quad (Right)
   glVertex3f 1.0, -1.5, -2.0                            Bottom Right Of The Quad (Right)
   glEnd                                                    Done Drawing The Quad

rquad -= 0.15

flip loop while inkey = ""</lang>

Frink

This program not only draws a cube and renders it onscreen projected on the x,y, and z axes but also outputs a .stl file for 3-D printing or display in a 3-D modeling package like MeshLab! Frink has built-in routines for 3-D modeling and can emit STL files or Wavefront OBJ files natively. <lang frink>res = 254 / in s = 1/2 inch res v = callJava["frink.graphics.VoxelArray", "cube", [-s, s, -s, s, -s, s, true]]

v.projectX[undef].show["X"] v.projectY[undef].show["Y"] v.projectZ[undef].show["Z"]

filename = "cube.stl" print["Writing $filename..."] w = new Writer[filename] w.println[v.toSTLFormat["cube", 1/(res mm)]] w.close[] println["done."]</lang>


Go

Translation of: PicoLisp

<lang go>package main

import "fmt"

func cuboid(dx, dy, dz int) {

   fmt.Printf("cuboid %d %d %d:\n", dx, dy, dz)
   cubLine(dy+1, dx, 0, "+-")
   for i := 1; i <= dy; i++ {
       cubLine(dy-i+1, dx, i-1, "/ |")
   }
   cubLine(0, dx, dy, "+-|")
   for i := 4*dz - dy - 2; i > 0; i-- {
       cubLine(0, dx, dy, "| |")
   }
   cubLine(0, dx, dy, "| +")
   for i := 1; i <= dy; i++ {
       cubLine(0, dx, dy-i, "| /")
   }
   cubLine(0, dx, 0, "+-\n")

}

func cubLine(n, dx, dy int, cde string) {

   fmt.Printf("%*s", n+1, cde[:1])
   for d := 9*dx - 1; d > 0; d-- {
       fmt.Print(cde[1:2])
   }
   fmt.Print(cde[:1])
   fmt.Printf("%*s\n", dy+1, cde[2:])

}

func main() {

   cuboid(2, 3, 4)
   cuboid(1, 1, 1)
   cuboid(6, 2, 1)

}</lang>

Output:
cuboid 2 3 4:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

cuboid 1 1 1:
  +--------+ 
 /        /|
+--------+ |
|        | |
|        | +
|        |/
+--------+

cuboid 6 2 1:
   +-----------------------------------------------------+ 
  /                                                     /|
 /                                                     / |
+-----------------------------------------------------+  |
|                                                     |  +
|                                                     | /
|                                                     |/
+-----------------------------------------------------+

Haskell

<lang haskell>import Graphics.Rendering.OpenGL import Graphics.UI.GLUT

-- Draw a cuboid. Its vertices are those of a unit cube, which is then scaled -- to the required dimensions. We only specify the visible faces, each of -- which is composed of two triangles. The faces are rotated into position and -- rendered with a perspective transformation.

type Fl = GLfloat

cuboid :: IO () cuboid = do

 color red   ; render front  
 color green ; render side
 color blue  ; render top

red,green,blue :: Color4 GLfloat red = Color4 1 0 0 1 green = Color4 0 1 0 1 blue = Color4 0 0 1 1

render :: [(Fl, Fl, Fl)] -> IO () render = renderPrimitive TriangleStrip . mapM_ toVertex

 where toVertex (x,y,z) = vertex $ Vertex3 x y z

front,side,top :: [(Fl,Fl,Fl)] front = vertices [0,1,2,3] side = vertices [4,1,5,3] top = vertices [3,2,5,6]

vertices :: [Int] -> [(Fl,Fl,Fl)] vertices = map (verts !!)

verts :: [(Fl,Fl,Fl)] verts = [(0,0,1), (1,0,1), (0,1,1), (1,1,1), (1,0,0), (1,1,0), (0,1,0)]

transform :: IO () transform = do

 translate $ Vector3 0 0 (-10 :: Fl)
 rotate (-14) $ Vector3 0 0 (1 :: Fl)
 rotate (-30) $ Vector3 0 1 (0 :: Fl)
 rotate   25  $ Vector3 1 0 (0 :: Fl)
 scale 2 3 (4 :: Fl)
 translate $ Vector3 (-0.5) (-0.5) (-0.5 :: Fl)

display :: IO () display = do

 clear [ColorBuffer]
 perspective 40 1 1 (15 :: GLdouble)
 transform
 cuboid
 flush

main :: IO () main = do

 let name = "Cuboid"
 initialize name []
 createWindow name
 displayCallback $= display
 mainLoop</lang>

J

Hack alert! I haven't even bothered to center the display. With larger resolutions and the viewmat script, this code can generate reasonable 2D displays with a different color for each face. <lang j> vectors =. ((% +/&.:*:"1) _1 1 0,:_1 _1 3) +/@:*"1/~ 2 3 4*=i.3

  ' .*o' {~  +/ 1 2 3* (|:"2 -."_ 1~ vectors) ([:*./ 1 = 0 1 I. %.~)"_ 1"_1 _ ]4j21 ,~"0/&:i: 4j41
                                         
                                         
                                         
                                         
                                         
                                         
                                         
                      oooo               
                 ooooooooooooo           
             oooooooooooooo....          
             *****oooo.........          
             *******...........          
             *******...........          
             *******...........          
             *******...........          
             *******...........          
             *******...........          
             *******...........          
             *******.........            
               *****.....                
                                         
                                         </lang>

Java

Works with: Java version 8

<lang java>import java.awt.*; import java.awt.event.*; import static java.lang.Math.*; import javax.swing.*;

public class Cuboid extends JPanel {

   double[][] nodes = {{-1, -1, -1}, {-1, -1, 1}, {-1, 1, -1}, {-1, 1, 1},
   {1, -1, -1}, {1, -1, 1}, {1, 1, -1}, {1, 1, 1}};
   int[][] edges = {{0, 1}, {1, 3}, {3, 2}, {2, 0}, {4, 5}, {5, 7}, {7, 6},
   {6, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}};
   int mouseX, prevMouseX, mouseY, prevMouseY;
   public Cuboid() {
       setPreferredSize(new Dimension(640, 640));
       setBackground(Color.white);
       scale(80, 120, 160);
       rotateCube(PI / 5, PI / 9);
       addMouseListener(new MouseAdapter() {
           @Override
           public void mousePressed(MouseEvent e) {
               mouseX = e.getX();
               mouseY = e.getY();
           }
       });
       addMouseMotionListener(new MouseAdapter() {
           @Override
           public void mouseDragged(MouseEvent e) {
               prevMouseX = mouseX;
               prevMouseY = mouseY;
               mouseX = e.getX();
               mouseY = e.getY();
               double incrX = (mouseX - prevMouseX) * 0.01;
               double incrY = (mouseY - prevMouseY) * 0.01;
               rotateCube(incrX, incrY);
               repaint();
           }
       });
   }
   private void scale(double sx, double sy, double sz) {
       for (double[] node : nodes) {
           node[0] *= sx;
           node[1] *= sy;
           node[2] *= sz;
       }
   }
   private void rotateCube(double angleX, double angleY) {
       double sinX = sin(angleX);
       double cosX = cos(angleX);
       double sinY = sin(angleY);
       double cosY = cos(angleY);
       for (double[] node : nodes) {
           double x = node[0];
           double y = node[1];
           double z = node[2];
           node[0] = x * cosX - z * sinX;
           node[2] = z * cosX + x * sinX;
           z = node[2];
           node[1] = y * cosY - z * sinY;
           node[2] = z * cosY + y * sinY;
       }
   }
   void drawCube(Graphics2D g) {
       g.translate(getWidth() / 2, getHeight() / 2);
       for (int[] edge : edges) {
           double[] xy1 = nodes[edge[0]];
           double[] xy2 = nodes[edge[1]];
           g.drawLine((int) round(xy1[0]), (int) round(xy1[1]),
                   (int) round(xy2[0]), (int) round(xy2[1]));
       }
       for (double[] node : nodes) {
           g.fillOval((int) round(node[0]) - 4, (int) round(node[1]) - 4, 8, 8);
       }
   }
   @Override
   public void paintComponent(Graphics gg) {
       super.paintComponent(gg);
       Graphics2D g = (Graphics2D) gg;
       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
       drawCube(g);
   }
   public static void main(String[] args) {
       SwingUtilities.invokeLater(() -> {
           JFrame f = new JFrame();
           f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           f.setTitle("Cuboid");
           f.setResizable(false);
           f.add(new Cuboid(), BorderLayout.CENTER);
           f.pack();
           f.setLocationRelativeTo(null);
           f.setVisible(true);
       });
   }

}</lang>

JavaScript

Translation of: Java

<lang javascript><!DOCTYPE html> <html lang="en">

<head>

   <meta charset="UTF-8">
   <style>
       canvas {
           background-color: black;
       }
   </style>

</head> <body>

   <canvas></canvas>
   <script>
       var canvas = document.querySelector("canvas");
       canvas.width = window.innerWidth;
       canvas.height = window.innerHeight;
       var g = canvas.getContext("2d");
       canvas.addEventListener("mousemove", function (event) {
           prevMouseX = mouseX;
           prevMouseY = mouseY;
           mouseX = event.x;
           mouseY = event.y;
           var incrX = (mouseX - prevMouseX) * 0.01;
           var incrY = (mouseY - prevMouseY) * 0.01;
           rotateCuboid(incrX, incrY);
           drawCuboid();
       });
       var nodes = [[-1, -1, -1], [-1, -1, 1], [-1, 1, -1], [-1, 1, 1],
       [1, -1, -1], [1, -1, 1], [1, 1, -1], [1, 1, 1]];
       var edges = [[0, 1], [1, 3], [3, 2], [2, 0], [4, 5], [5, 7], [7, 6],
       [6, 4], [0, 4], [1, 5], [2, 6], [3, 7]];
       var mouseX = 0, prevMouseX, mouseY = 0, prevMouseY;
       function scale(factor0, factor1, factor2) {
           nodes.forEach(function (node) {
               node[0] *= factor0;
               node[1] *= factor1;
               node[2] *= factor2;
           });
       }
       function rotateCuboid(angleX, angleY) {
           var sinX = Math.sin(angleX);
           var cosX = Math.cos(angleX);
           var sinY = Math.sin(angleY);
           var cosY = Math.cos(angleY);
           nodes.forEach(function (node) {
               var x = node[0];
               var y = node[1];
               var z = node[2];
               node[0] = x * cosX - z * sinX;
               node[2] = z * cosX + x * sinX;
               z = node[2];
               node[1] = y * cosY - z * sinY;
               node[2] = z * cosY + y * sinY;
           });
       }
       function drawCuboid() {
           g.save();
           
           g.clearRect(0, 0, canvas.width, canvas.height);
           g.translate(canvas.width / 2, canvas.height / 2);
           g.strokeStyle = "#FFFFFF";
           g.beginPath();
           edges.forEach(function (edge) {
               var p1 = nodes[edge[0]];
               var p2 = nodes[edge[1]];
               g.moveTo(p1[0], p1[1]);
               g.lineTo(p2[0], p2[1]);
           });
           
           g.closePath();
           g.stroke();
           g.restore();
       }
       scale(80, 120, 160);
       rotateCuboid(Math.PI / 5, Math.PI / 9);
   </script>

</body> </html></lang>

Julia

ASCII Art

Translation of: Python
Works with: Julia version 0.6

<lang julia>_pr(t::Dict, x::Int, y::Int, z::Int) = join((rstrip(join(t[(n, m)] for n in range(0, 3+x+z))) for m in reverse(range(0, 3+y+z))), "\n")

function cuboid(x::Int, y::Int, z::Int)

   t = Dict((n, m) => " " for n in range(0, 3 + x + z), m in range(0, 3 + y + z))
   xrow = vcat("+", collect("$(i % 10)" for i in range(0, x)), "+")
   for (i, ch) in enumerate(xrow) t[(i, 0)] = t[(i, 1+y)] = t[(1+z+i, 2+y+z)] = ch end
   yrow = vcat("+", collect("$(j % 10)" for j in range(0, y)), "+")
   for (j, ch) in enumerate(yrow) t[(0, j)] = t[(x+1, j)] = t[(2+x+z, 1+z+j)] = ch end
   zdep = vcat("+", collect("$(k % 10)" for k in range(0, y)), "+")
   for (k, ch) in enumerate(xrow) t[(k, 1+y+k)] = t[(1+x+k, 1+y+k)] = t[(1+x+k, k)] = ch end
   return _pr(t, x, y, z)

end

for (x, y, z) in [(2, 3, 4), (3, 4, 2), (4, 2, 3), (5, 5, 6)]

   println("\nCUBOID($x, $y, $z)\n")
   println(cuboid(x, y, z))

end</lang>

Output:
CUBOID(2, 3, 4)

      +02
    +  +1
   1  1 0
  0  0  +
++ ++
2+02+  +
1  1  1
0  0 0
+  ++
 +01+

CUBOID(3, 4, 2)

   1+011
  0   02
++  ++ 1
3+013+ 0
2   2  +
1   1  1
0   0 0
+   ++
 +012+

CUBOID(4, 2, 3)

    2+0122
   1    10
  0    0 +
++   ++  2
1+0121+ 1
0    0 0
+    ++
 +0123+

CUBOID(5, 5, 6)

       ++0123+
      4     43
     3     3 2
    2     2  1
   1     1   0
  0     0    +
++    ++     +
4+01234+    4
3     3    3
2     2   2
1     1  1
0     0 0
+     ++
 +01234+

Kotlin

Translation of: Java

<lang scala>// version 1.1

import java.awt.* import java.awt.event.MouseAdapter import java.awt.event.MouseEvent import javax.swing.*

class Cuboid: JPanel() {

   private val nodes = arrayOf(
       doubleArrayOf(-1.0, -1.0, -1.0),
       doubleArrayOf(-1.0, -1.0,  1.0),
       doubleArrayOf(-1.0,  1.0, -1.0),
       doubleArrayOf(-1.0,  1.0,  1.0),
       doubleArrayOf( 1.0, -1.0, -1.0),
       doubleArrayOf( 1.0, -1.0,  1.0),
       doubleArrayOf( 1.0,  1.0, -1.0),
       doubleArrayOf( 1.0,  1.0,  1.0)
   )
   private val edges = arrayOf(
       intArrayOf(0, 1),
       intArrayOf(1, 3),
       intArrayOf(3, 2),
       intArrayOf(2, 0),
       intArrayOf(4, 5),
       intArrayOf(5, 7),
       intArrayOf(7, 6),
       intArrayOf(6, 4),
       intArrayOf(0, 4),
       intArrayOf(1, 5),
       intArrayOf(2, 6),
       intArrayOf(3, 7)
   )
   private var mouseX: Int = 0
   private var prevMouseX: Int = 0
   private var mouseY: Int = 0
   private var prevMouseY: Int = 0
   init {
       preferredSize = Dimension(640, 640)
       background = Color.white
       scale(80.0, 120.0, 160.0)
       rotateCube(Math.PI / 5.0, Math.PI / 9.0)
       addMouseListener(object: MouseAdapter() {
           override fun mousePressed(e: MouseEvent) {
               mouseX = e.x
               mouseY = e.y
           }
       })
       addMouseMotionListener(object: MouseAdapter() {
           override fun mouseDragged(e: MouseEvent) {
               prevMouseX = mouseX
               prevMouseY = mouseY
               mouseX = e.x
               mouseY = e.y
               val incrX = (mouseX - prevMouseX) * 0.01
               val incrY = (mouseY - prevMouseY) * 0.01
               rotateCube(incrX, incrY)
               repaint()
           }
       })
   }
   private fun scale(sx: Double, sy: Double, sz: Double) {
       for (node in nodes) {
           node[0] *= sx
           node[1] *= sy
           node[2] *= sz
       }
   }
   private fun rotateCube(angleX: Double, angleY: Double) {
       val sinX = Math.sin(angleX)
       val cosX = Math.cos(angleX)
       val sinY = Math.sin(angleY)
       val cosY = Math.cos(angleY)
       for (node in nodes) {
           val x = node[0]
           val y = node[1]
           var z = node[2]
           node[0] = x * cosX - z * sinX
           node[2] = z * cosX + x * sinX
           z = node[2]
           node[1] = y * cosY - z * sinY
           node[2] = z * cosY + y * sinY
       }
   }
   private fun drawCube(g: Graphics2D) {
       g.translate(width / 2, height / 2)
       for (edge in edges) {
           val xy1 = nodes[edge[0]]
           val xy2 = nodes[edge[1]]
           g.drawLine(Math.round(xy1[0]).toInt(), Math.round(xy1[1]).toInt(),
                      Math.round(xy2[0]).toInt(), Math.round(xy2[1]).toInt())
       }
       for (node in nodes) {
           g.fillOval(Math.round(node[0]).toInt() - 4, Math.round(node[1]).toInt() - 4, 8, 8)
       }
   }
   override public fun paintComponent(gg: Graphics) {
       super.paintComponent(gg)
       val g = gg as Graphics2D
       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
       g.color = Color.blue
       drawCube(g)
   }

}

fun main(args: Array<String>) {

   SwingUtilities.invokeLater {
       val f = JFrame()
       f.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
       f.title = "Cuboid"
       f.isResizable = false
       f.add(Cuboid(), BorderLayout.CENTER)
       f.pack()
       f.setLocationRelativeTo(null)
       f.isVisible = true
   }

}</lang>

Liberty BASIC

Text solution <lang lb> Call cuboid 1,3,4

End

Sub cuboid width, height, depth

   wd=width*7+2: hi=height*3: dp=depth
   For i=1 To wd-2
       w$=w$+"-":h$=h$+" "
   Next
   w$="+"+w$+"+":d$="/"+h$+"/":h$="|"+h$+"|"
   px=dp+2:py=1:Locate dp+2,py:Print w$;
   For i=2 To hi+1
       Locate wd+dp+1,i:Print"|";
   Next
   Locate wd+dp+1, i: Print "+";
   For i=dp+1 To 1 Step -1
       py=py+1:Locate i,py:Print d$;
   Next
   For i=1 To dp
       Locate wd+(dp+1)-i,hi+d+2+i:Print "/";
   Next
   Locate 1, dp+2: Print w$;
   For i=dp+3 To hi+dp+2
       Locate 1,i:Print h$;
   Next
   Locate 1, dp+hi+3: Print w$

End Sub </lang>

Output:
     +-------+
    /       /|
   /       / |
  /       /  |
 /       /   |
+-------+    |
|       |    |
|       |    |
|       |    |
|       |    |
|       |    +
|       |   /
|       |  /
|       | /
|       |/
+-------+

Graphic solution <lang lb> NoMainWin Global sw, sh sw = 400: sh = 400 WindowWidth = sw+6 WindowHeight= sh+32 Open "[RC] Draw Cuboid" For graphics_nsb_nf As #g

  1. g "Down; Fill black; TrapClose [xit]"
  2. g "when leftButtonDown [xit]"

Call drawCuboid 3,4,5

Wait

[xit] Close #g End

Sub drawCuboid width, height, depth

   wd = width*50
   ht = height*50
   dp = depth*20
   sx = Int((sw-(wd+dp))/2)
   sy = Int((sh-(ht-dp))/2)
   #g "Color 0 128 255; BackColor 0 128 255"
   #g "Place ";sx;" ";sy
   #g "boxFilled ";sx+wd;" ";sy+ht
   x1 = sx+dp : y1 = sy-dp
   x2 = x1+wd-1 : y2 = y1+1
   #g "Color 0 64 128"
   Call triFill sx,sy, x1,y1, x2,y2
   Call triFill sx,sy, x2,y2, sx+wd, sy
   #g "Color 0 96 192"
   x3 = x2: y3 = y2+ht
   Call triFill x2,y2, x3,y3, sx+wd-1, sy+ht-1
   Call triFill x2,y2, sx+wd-1, sy+ht-1, sx+wd-1, sy
   #g "Color white;BackColor black;Place 5 20"
   #g "\Size: ";width;", ";height;", ";depth

End Sub

Sub triFill x1,y1, x2,y2, x3,y3

   If x2<x1 Then x=x2: y=y2: x2=x1: y2=y1: x1=x: y1=y
   If x3<x1 Then x=x3: y=y3: x3=x1: y3=y1: x1=x: y1=y
   If x3<x2 Then x=x3: y=y3: x3=x2: y3=y2: x2=x: y2=y
   If x1<>x3 Then slope1=(y3-y1)/(x3-x1)
   length=x2-x1
   If length<>0 Then
       slope2=(y2-y1)/(x2-x1)
       For x = 0 To length
           #g "Line ";Int(x+x1);" ";Int(x*slope1+y1);" ";Int(x+x1);" ";Int(x*slope2+y1)
       Next
   End If
   y = length*slope1+y1 :length=x3-x2
   If length<>0 Then
       slope3=(y3-y2)/(x3-x2)
       For x = 0 To length
           #g "Line ";Int(x+x2);" ";Int(x*slope1+y);" ";Int(x+x2);" ";Int(x*slope3+y2)
       Next
   End If

End Sub </lang>

In Logo, we can use the perspective function to make drawing 3D-objects easier.

Works with: MSWlogo

Simple implementation, just moving to the appropriate points every time. <lang logo>to cuboid :l1 :l2 :l3 cs perspective ;making the room ready to use setxyz :l1 0 0 setxyz :l1 :l2 0 setxyz 0 :l2 0 setxyz 0 0 0 setxyz :l1 0 0 setxyz :l1 0 -:l3 setxyz :l1 :l2 -:l3 setxyz :l1 :l2 0 setxyz 0 :l2 0 setxyz 0 :l2 -:l3 setxyz :l1 :l2 -:l3 end</lang> Example call to achieve task: <lang logo>cuboid 50 100 150</lang>

LSL

Rez a box on the ground, raise it up a few meters, add the following as a New Script. <lang LSL>vector vSCALE = <2.0, 3.0, 4.0>; default {

   state_entry() {
       llSetScale(vSCALE);
   }

}</lang>

Output:

Ahhhhh; I always wondered what a Cuboid looked like, now I know!

)

Draw a Cuboid
A Cuboid in a Sandbox.


Lua

Begin with the code in the Draw_a_rotating_cube task, then extend the cube object as follows: <lang lua>-- needed for actual task cube.scale = function(self, sx, sy, sz)

 for i,v in ipairs(self.verts) do
   v[1], v[2], v[3] = v[1]*sx, v[2]*sy, v[3]*sz
 end

end -- only needed for output -- (to size it for screen, given a limited camera) cube.translate = function(self, tx, ty, tz)

 for i,v in ipairs(self.verts) do
   v[1], v[2], v[3] = v[1]+tx, v[2]+ty, v[3]+tz
 end

end</lang> Then replace all of the "demo" code below the empty comment line "--" with: <lang lua>-- bitmap:init(40,40) cube:scale(2,3,4) cube:rotate(-pi/4, -pi/6) cube:translate(0,0,10) bitmap:clear("··") renderer:render(cube, camera, bitmap) screen:clear() bitmap:render()</lang>

Output:
················································································
················································································
················································································
················································································
················································································
··························████··················································
················██████████··██████████··········································
········████████············██········████████··································
········██████··············██················██████····························
········██····██████········██······················████████····················
········██··········████····██······························████████············
··········██············██████······································██████······
··········██··················████··································██████······
··········██··················██··████··························████····██······
··········██··················██······██████················████······██········
··········██··················██············████········████··········██········
············██················██················████████··············██········
············██················██····················██················██········
············██················██····················██··············██··········
············██················██····················██··············██··········
············██··············████····················██··············██··········
············██··········████····██··················██··············██··········
··············██····████··········████············██················██··········
··············██████··················████········██··············██············
··············██··························████····██··············██············
················██····························██████··············██············
··················██······························████············██············
····················██····························██··████······██··············
······················██··························██······████··██··············
························████······················██··········████··············
····························██····················██··········██················
······························██··················██········██··················
································████··············██······██····················
····································██··········██······██······················
······································██········██····██························
········································████····██··██··························
············································██··████····························
··············································████······························
················································································
················································································

Maple

This creates a cuboid with one corner at (0,0,0) and the opposite at (2,3,4): <lang Maple>plots:-display(plottools:-parallelepiped([2, 0, 0], [0, 0, 4], [0, 3, 0]), orientation = [45, 60])</lang>

Mathematica / Wolfram Language

This creates a cuboid with one corner at (0,0,0) and the opposite at (2,3,4): <lang Mathematica>Graphics3D[Cuboid[{0,0,0},{2,3,4}]]</lang> Output would be fully-rendered, rotatable 3D in the notebook. Also, many aspects of the cuboid's appearance and lighting can be controlled quite easily. For those, see Mathematica's documentation in the program or on the web.

Maxima

<lang maxima>load(draw)$

draw3d(xu_grid=100, yv_grid=100, surface_hide=true,

  palette=gray, enhanced3d=[x - z / 4 - y / 4, x, y, z],
  implicit(max(abs(x / 4), abs(y / 6), abs(z / 8)) = 1,
  x,-10,10,y,-10,10,z,-10,10))$</lang>

Nim

Translation of: PicoLisp

<lang nim>import strutils

proc cline(n, x, y: int, cde: string) =

 echo cde[0..0].align n+1,
   repeat(cde[1], 9*x-1),
   cde[0],
   if cde.len > 2: cde[2..2].align y+1 else: ""

proc cuboid(x, y, z: int) =

 cline y+1, x, 0, "+-"
 for i in 1..y: cline y-i+1, x, i-1, "/ |"
 cline 0, x, y, "+-|"
 for i in 0..4*z-y-3: cline 0, x, y, "| |"
 cline 0, x, y, "| +"
 for i in countdown(y-1, 0): cline 0, x, i, "| /"
 cline 0, x, 0, "+-\n"

cuboid 2, 3, 4 cuboid 1, 1, 1 cuboid 6, 2, 1</lang>

Output:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

  +--------+ 
 /        /|
+--------+ |
|        | |
|        | +
|        |/
+--------+

   +-----------------------------------------------------+ 
  /                                                     /|
 /                                                     / |
+-----------------------------------------------------+  |
|                                                     |  +
|                                                     | /
|                                                     |/
+-----------------------------------------------------+

Openscad

Drawing a cuboid is easy in openscad:

<lang openscad>// This will produce a simple cuboid cube([2,3,4]); </lang>

OxygenBasic

Using an OpenGl-based console <lang>

 % Title "Cuboid 2x3x4"
 '% Animated
 % PlaceCentral
 uses ConsoleG
 sub main
 ========
 cls 0.0, 0.2, 0.7
 shading
 scale 3
 pushstate
   GoldMaterial.act
   static float ang=45
   rotateX ang
   rotateY ang
   scale 2,3,4
   go cube
 popstate
 end sub
 EndScript

</lang>

PARI/GP

Output Cuboid1.png
Output Cuboid2.png

Plotting lines and scaling in PARI/GP is not designed for "cuboids". But you are welcome to play with parameters of this Cuboid() function.

Works with: PARI/GP version 2.7.4 and above

<lang parigp> \\ Simple "cuboid". Try different parameters of this Cuboid() function. \\ 4/11/16 aev Cuboid(a,b,c,u=10)={ my(dx,dy,ttl="Cuboid AxBxC: ",size=200,da=a*u,db=b*u,dc=c*u); print(" *** ",ttl,a,"x",b,"x",c,"; u=",u); plotinit(0); plotscale(0, 0,size, 0,size); plotcolor(0,7); \\grey plotmove(0, 0,0); plotrline(0,dc,da\2); plotrline(0,db,0); plotrline(0,-db,0); plotrline(0,0,da); plotcolor(0,2); \\black plotmove(0, db,da); plotrline(0,0,-da); plotrline(0,-db,0); plotrline(0,0,da); plotrline(0,db,0); plotrline(0,dc,da\2); plotrline(0,-db,0); plotrline(0,-dc,-da\2); plotmove(0, db,0); plotrline(0,dc,da\2); plotrline(0,0,da); plotdraw([0,size,size]); }

{\\ Executing: Cuboid(2,3,4,20); \\Cuboid1.png Cuboid(5,3,1,20); \\Cuboid2.png } </lang>

Output:
> Cuboid(2,3,4,20); \\Cuboid1.png
*** Cuboid AxBxC: 2x3x4; u=20
> Cuboid(5,3,1,20); \\Cuboid2.png
*** Cuboid AxBxC: 5x3x1; u=20

Pascal

Translation of: Ada
Works with: Free_Pascal

<lang pascal>program Cuboid_Demo(output);

procedure DoCuboid(sWidth, sHeight, Depth: integer);

 const
   widthScale  = 4;
   heightScale = 3;
 type
   TPage = array of array of char;
 var
   Cuboid: TPage;
   i, j: integer;
   Width, Height: integer;
   totalWidth, totalHeight: integer;
 begin
   Width  := widthScale  * sWidth;
   Height := heightScale * sHeight;    
   totalWidth  := 2 * Width + Depth + 3;
   totalHeight := Height + Depth + 3;
   setlength (Cuboid, totalHeight + 1);
   for i := 1 to totalHeight do
     setlength (Cuboid[i], totalwidth + 1);
   // points
   for i := low(Cuboid) to high(Cuboid) do
     for j := low(Cuboid[i]) to high(Cuboid[i]) do
       Cuboid[i,j] := ' ';
   Cuboid [1, 1]                      := '+';
   Cuboid [Height + 2, 1]             := '+';
   Cuboid [1, 2 * Width + 2]          := '+';
   Cuboid [Height + 2, 2 * Width + 2] := '+';
   Cuboid [totalHeight, Depth + 2]    := '+';
   Cuboid [Depth + 2, totalWidth]     := '+';
   Cuboid [totalHeight, totalWidth]   := '+';
   // width lines
   for I := 1 to 2 * Width do
   begin
      Cuboid [1, I + 1]                   := '-';
      Cuboid [Height + 2, I + 1]          := '-';
      Cuboid [totalHeight, Depth + I + 2] := '-';
   end;
   // height lines
   for I := 1 to Height do
   begin
      Cuboid [I + 1, 1]                  := '|';
      Cuboid [I + 1, 2 * Width + 2]      := '|';
      Cuboid [Depth + I + 2, totalWidth] := '|';
   end;
   // depth lines
   for I := 1 to Depth do
   begin
      Cuboid [Height + 2 + I, 1 + I]             := '/';
      Cuboid [1 + I, 2 * Width + 2 + I]          := '/';
      Cuboid [Height + 2 + I, 2 * Width + 2 + I] := '/';
   end;
   for i := high(Cuboid) downto 1 do
   begin
     for j := 1 to high(Cuboid[i]) do
       write (Cuboid[i,j]);
     writeln;
   end;
 end;  

begin

 writeln('1, 1, 1:');
 DoCuboid(1, 1, 1);
 writeln('2, 3, 4:');
 DoCuboid(2, 3, 4);
 writeln('6, 2, 1:');
 DoCuboid(6, 2, 1);

end.</lang>

Output:
% ./Cuboid
1, 1, 1:
  +--------+
 /        /|
+--------+ |
|        | |
|        | +
|        |/ 
+--------+  
2, 3, 4:
     +----------------+
    /                /|
   /                / |
  /                /  |
 /                /   |
+----------------+    |
|                |    |
|                |    |
|                |    |
|                |    |
|                |    +
|                |   / 
|                |  /  
|                | /   
|                |/    
+----------------+     
6, 2, 1:
  +------------------------------------------------+
 /                                                /|
+------------------------------------------------+ |
|                                                | |
|                                                | |
|                                                | |
|                                                | |
|                                                | +
|                                                |/ 
+------------------------------------------------+ 

Perl

Translation of: Go

<lang perl>sub cubLine ($$$$) {

   my ($n, $dx, $dy, $cde) = @_;
   printf '%*s', $n + 1, substr($cde, 0, 1);
   for (my $d = 9 * $dx - 1 ; $d > 0 ; --$d) {
       print substr($cde, 1, 1);
   }
   print substr($cde, 0, 1);
   printf "%*s\n", $dy + 1, substr($cde, 2, 1);

}

sub cuboid ($$$) {

   my ($dx, $dy, $dz) = @_;
   printf "cuboid %d %d %d:\n", $dx, $dy, $dz;
   cubLine $dy + 1, $dx, 0, '+-';
   for (my $i = 1 ; $i <= $dy ; ++$i) {
       cubLine $dy - $i + 1, $dx, $i - 1, '/ |';
   }
   cubLine 0, $dx, $dy, '+-|';
   for (my $i = 4 * $dz - $dy - 2 ; $i > 0 ; --$i) {
       cubLine 0, $dx, $dy, '| |';
   }
   cubLine 0, $dx, $dy, '| +';
   for (my $i = 1 ; $i <= $dy ; ++$i) {
       cubLine 0, $dx, $dy - $i, '| /';
   }
   cubLine 0, $dx, 0, "+-\n";

}

cuboid 2, 3, 4; cuboid 1, 1, 1; cuboid 6, 2, 1;</lang>

Output:
cuboid 2 3 4:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

cuboid 1 1 1:
  +--------+ 
 /        /|
+--------+ |
|        | |
|        | +
|        |/
+--------+

cuboid 6 2 1:
   +-----------------------------------------------------+ 
  /                                                     /|
 /                                                     / |
+-----------------------------------------------------+  |
|                                                     |  +
|                                                     | /
|                                                     |/
+-----------------------------------------------------+

ASCII Art <lang perl>use 5.010;

  1. usage: script X Y Z [S]

sub cuboid {

   # Constant dimnesions of the cuboid
   my ($x, $y, $z) = map int, @_[0 .. 2];
   # ASCII characters
   # $c = corner point
   # $h = horizontal line
   # $v = vertical line
   # $d = diagonal line
   # $s = space (inside the cuboid)
   my ($c, $h, $v, $d, $s) = ('+', '-', '|', '/', shift(@ARGV) // q{ });
   say q{ } x ($z + 1), $c, $h x $x, $c;
   say q{ } x ($z - $_ + 1), $d, $s x $x, $d, $s x ($_ - ($_ > $y ? ($_ - $y) : 1)),
     $_ - 1 == $y ? $c : $_ > $y ? $d : $v for 1 .. $z;
   say $c, $h x $x, $c, ($s x ($z < $y ? $z : $y), $z < $y ? $v : $z == $y ? $c : $d);
   say $v, $s x $x, $v, $z > $y ? $_ >= $z ? ($s x $x, $c) : ($s x ($y - $_), $d)
     : $y - $_ > $z ? ($s x $z, $v) : ($s x ($y - $_), $y - $_ == $z ? $c : $d) for 1 .. $y;
   say $c, $h x $x, $c;

}

cuboid shift // rand 20, shift // rand 10, shift // rand 10;</lang>

Cuboid(2,3,4)

     +--+
    /  /|
   /  / |
  /  /  |
 /  /   +
+--+   /
|  |  /
|  | /
|  |/
+--+

Phix

Library: Phix/pGUI
Library: Phix/online

Translated from XPL0.
Press space to toggle auto-rotate on and off, cursor keys to rotate manually, and +/- to zoom in/out. Simple orthogonal projection, no perspective. You can run this online here.

--
-- demo\rosetta\draw_cuboid.exw
-- ============================
--
-- Author Pete Lomax, August 2015
--  Translated from XPL0.
--  Ported to pGUI August 2017
--
--  Press space to toggle auto-rotate on and off,
--        cursor keys to rotate manually, and 
--        +/- to zoom in/out.
--
--  Note this uses simple orthogonal projection;
--            there is no perspective here!
--            (For that see DrawRotatingCube.exw)
--
with javascript_semantics
include pGUI.e

constant title = "Draw Cuboid"
Ihandle dlg, canvas, hTimer
cdCanvas cd_canvas

-- arrays: 3D coordinates of vertices
sequence x = {-2.0, +2.0, +2.0, -2.0,  -2.0, +2.0, +2.0, -2.0},
         y = {-1.5, -1.5, +1.5, +1.5,  -1.5, -1.5, +1.5, +1.5},
         z = {-1.0, -1.0, -1.0, -1.0,  +1.0, +1.0, +1.0, +1.0}

constant segments = {{1,2}, {2,3}, {3,4}, {4,1}, {5,6}, {6,7},
                     {7,8}, {8,5}, {1,5}, {2,6}, {3,7}, {4,8}}

atom Size = 50.0,       -- drawing size 
     Sz = 0.008,        -- tumbling speeds
     Sx =-0.013,        -- ""
     Sy = 0.005,        -- ""
     S = 2

procedure draw_cube(integer cx, cy)
    -- {cx,cy} is the centre point of the canvas
    integer farthest = largest(z,true)
    for s=1 to length(segments) do
        integer {va,vb} = segments[s],
                  bNear = not find(farthest,segments[s])
        cdCanvasSetForeground(cd_canvas, iff(bNear?CD_RED:CD_BLUE))
        cdCanvasSetLineStyle(cd_canvas, iff(bNear?CD_CONTINUOUS:CD_DASHED)) 
        atom x1 = x[va]*Size+cx,
             y1 = y[va]*Size+cy,
             x2 = x[vb]*Size+cx,
             y2 = y[vb]*Size+cy
        cdCanvasLine(cd_canvas,x1,y1,x2,y2)
    end for
end procedure

function canvas_action_cb(Ihandle canvas)
    cdCanvasActivate(cd_canvas)
    cdCanvasClear(cd_canvas)
    integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE")
    draw_cube(floor(w/2),floor(h/2))
    cdCanvasFlush(cd_canvas)
    return IUP_DEFAULT
end function

function canvas_map_cb(Ihandle canvas)
    IupGLMakeCurrent(canvas)
    if platform()=JS then
        cd_canvas = cdCreateCanvas(CD_IUP, canvas)
    else
        atom res = IupGetDouble(NULL, "SCREENDPI")/25.4
        cd_canvas = cdCreateCanvas(CD_GL, "10x10 %g", {res})
    end if
--  cdCanvasSetBackground(cd_canvas, CD_PARCHMENT)
    cdCanvasSetBackground(cd_canvas, CD_BLACK)
    return IUP_DEFAULT
end function

function canvas_unmap_cb(Ihandle canvas)
    cdKillCanvas(cd_canvas)
    return IUP_DEFAULT
end function

function canvas_resize_cb(Ihandle /*canvas*/)
    integer {canvas_width, canvas_height} = IupGetIntInt(canvas, "DRAWSIZE")
    atom res = IupGetDouble(NULL, "SCREENDPI")/25.4
    cdCanvasSetAttribute(cd_canvas, "SIZE", "%dx%d %g", {canvas_width, canvas_height, res})
    return IUP_DEFAULT
end function

function key_cb(Ihandle /*ih*/, atom c)
    if c=K_ESC then 
        return IUP_CLOSE
    elsif c=K_UP then
        for i=1 to 8 do
            y[i] += z[i]*Sx*S   -- rotate vertices in Y-Z plane
            z[i] -= y[i]*Sx*S
        end for
    elsif c=K_DOWN then
        for i=1 to 8 do
            y[i] -= z[i]*Sx*S   -- rotate vertices in Y-Z plane
            z[i] += y[i]*Sx*S
        end for
    elsif c=K_LEFT then
        for i=1 to 8 do
            x[i] += z[i]*Sy*S   -- rotate vertices in X-Z plane
            z[i] -= x[i]*Sy*S
        end for
    elsif c=K_RIGHT then
        for i=1 to 8 do
            x[i] -= z[i]*Sy*S   -- rotate vertices in X-Z plane
            z[i] += x[i]*Sy*S
        end for
    elsif c='+' then
        Size = min(500,Size+5)
    elsif c='-' then
        Size = max( 10,Size-5)
    elsif c=' ' then
        IupSetInt(hTimer,"RUN",not IupGetInt(hTimer,"RUN"))
    end if
    IupUpdate(canvas)
    return IUP_CONTINUE
end function

function timer_cb(Ihandle /*ih*/)
    for i=1 to 8 do
        x[i] = x[i]+y[i]*Sz*S   -- rotate vertices in X-Y plane
        y[i] = y[i]-x[i]*Sz*S
        y[i] = y[i]+z[i]*Sx*S   -- rotate vertices in Y-Z plane
        z[i] = z[i]-y[i]*Sx*S
        x[i] = x[i]+z[i]*Sy*S   -- rotate vertices in X-Z plane
        z[i] = z[i]-x[i]*Sy*S
    end for
    IupUpdate(canvas)
    return IUP_IGNORE
end function

procedure main()
    IupOpen()
    canvas = IupGLCanvas("RASTERSIZE=640x480")
    IupSetCallbacks(canvas, {"ACTION", Icallback("canvas_action_cb"),
                             "MAP_CB", Icallback("canvas_map_cb"),
                             "UNMAP_CB", Icallback("canvas_unmap_cb"),
                             "RESIZE_CB", Icallback("canvas_resize_cb")})
--  dlg = IupDialog(IupVbox({canvas}),`TITLE="%s"`,{title})
    dlg = IupDialog(canvas,`TITLE="%s"`,{title})
    IupSetCallback(dlg, "KEY_CB",  Icallback("key_cb"))
    IupShow(dlg)
    IupSetAttribute(canvas, "RASTERSIZE", NULL)
    hTimer = IupTimer(Icallback("timer_cb"), 40)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()

ascii

Two versions: the first uses a complete/rectangular grid and outputs at the end, whereas the second uses a slightly trickier line-by-line approach.

with javascript_semantics
function draw_line(sequence res, integer x,y,dx,dy,len,c)
    string line = '+'&repeat(c,len-2)&'+'
    for i=1 to len do
        res[y,x] = line[i]
        y += dy; x += dx
    end for
    return res
end function
 
procedure ascii_cuboid(integer x,y,z)
    sequence res = repeat(repeat(' ',x+z+3),y+z+3)
    res = draw_line(res,    1,  z+2,+1,-1,z+2,'/')
    res = draw_line(res,  x+2,  z+2,+1,-1,z+2,'/')
    res = draw_line(res,  x+2,y+z+3,+1,-1,z+2,'/')
    res = draw_line(res,    1,  z+2, 0,+1,y+2,'|')
    res = draw_line(res,  x+2,  z+2, 0,+1,y+2,'|')
    res = draw_line(res,x+z+3,    1, 0,+1,y+2,'|')
    res = draw_line(res,  z+2,    1,+1, 0,x+2,'-')
    res = draw_line(res,    1,  z+2,+1, 0,x+2,'-')
    res = draw_line(res,    1,y+z+3,+1, 0,x+2,'-')
    printf(1,"%s\n",{join(res,"\n")})
end procedure
ascii_cuboid(0,0,0)
ascii_cuboid(1,1,1)
ascii_cuboid(2,1,2)
ascii_cuboid(3,2,1)
Output:
 ++
+++
++
  +-+
 / /|
+-+ +
| |/
+-+
   +--+
  /  /|
 /  / +
+--+ /
|  |/
+--+
  +---+
 /   /|
+---+ |
|   | +
|   |/
+---+

And as promised a line-by-line solution. Same output.

with javascript_semantics
procedure cuboid(integer x,y,z)
--
--                                        +-+   -- 1) (with x -)
--                                       / /|   -- 2) (times z)
--  Output an x by y by z cube such as  +-+ +   -- 3) (with x -)
--                                      | |/    -- 4) (times y)
--                                      +-+     -- 5) (with x -)
--
--  Nb: trailing '+' shown on stage 3 can occur higher or lower.
--
    integer mn = min(y,z)+1, mx = max(y,z)+1,
            stage = 1, -- (1..5 as above)
            pre = z+1, spc = -1, last = 1
    for l=1 to y+z+3 do
        integer c = "+/+|+"[stage]   -- (front/top corner/edge)
        puts(1,repeat(' ',pre)&c&repeat(iff(c='+'?'-':' '),x)&c&
               iff(spc>=0?repeat(' ',spc)&"|+/"[last]:"")&"\n")
        pre -= pre>0   -- (shrink the initial lhs space prefix)
        spc += (l<=mn)-(l>mx) -- +1 early on, -1 later, or both
        stage += (c='+') + (l=z+1 or l=y+z+2) -- (can skip 2&4)
        last += (last=2 or l=y+1 or l=y+z+2) -- ('|'->'+'->'/')
    end for
end procedure
cuboid(0, 0, 0)
cuboid(1, 1, 1)
cuboid(2, 1, 2)
cuboid(3, 2, 1)

PicoLisp

Using ASCII

<lang PicoLisp>(de cuboid (DX DY DZ)

  (cubLine (inc DY) "+" DX "-" 0)
  (for I DY
     (cubLine (- DY I -1) "/" DX " " (dec I) "|") )
  (cubLine 0 "+" DX "-" DY "|")
  (do (- (* 4 DZ) DY 2)
     (cubLine 0 "|" DX " " DY "|") )
  (cubLine 0 "|" DX " " DY "+")
  (for I DY
     (cubLine 0 "|" DX " " (- DY I) "/") )
  (cubLine 0 "+" DX "-" 0) )

(de cubLine (N C DX D DY E)

  (space N)
  (prin C)
  (do (dec (* 9 DX)) (prin D))
  (prin C)
  (space DY)
  (prinl E) )</lang>
Output:
: (cuboid 2 3 4)
    +-----------------+
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

: (cuboid 1 1 1)
  +--------+
 /        /|
+--------+ |
|        | |
|        | +
|        |/
+--------+

: (cuboid 6 2 1)
   +-----------------------------------------------------+
  /                                                     /|
 /                                                     / |
+-----------------------------------------------------+  |
|                                                     |  +
|                                                     | /
|                                                     |/
+-----------------------------------------------------+

Using OpenGL

Library: GLUT

<lang PicoLisp>(load "@lib/openGl.l")

(setq *AngleX -26.0 *AngleY 74.0) (setq *LastX 0 *LastY 0)

(glutInit) (glutInitDisplayMode (| GLUT_RGBA GLUT_DOUBLE GLUT_DEPTH)) (glutInitWindowSize 512 512) (glutInitWindowPosition 10 50) (glutCreateWindow "PicoLisp Cube")

(glClearColor 1.0 1.0 1.0 1.0) # The background color (glEnable GL_DEPTH_TEST) (glEnable GL_LIGHTING) (glEnable GL_LIGHT0) (glDisable GL_CULL_FACE)

(glEnable GL_BLEND) (glBlendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA) (glEnable GL_LINE_SMOOTH) (glHint GL_LINE_SMOOTH_HINT GL_NICEST) (glLineWidth 2.0)

(mouseFunc

  '((Btn State X Y)
     (setq *LastX X  *LastY Y) ) )

(motionFunc

  '((X Y)
     (inc '*AngleX (* (- Y *LastY) 1.0))
     (inc '*AngleY (* (- X *LastX) 1.0))
     (setq *LastX X  *LastY Y)
     (glutPostRedisplay) ) )

(reshapeFunc

  '((Width Height)
     (glMatrixMode GL_PROJECTION)
     (glLoadIdentity)
     (gluPerspective 45.0 (*/ Width 1.0 Height) 1.0 10.0)
     (glMatrixMode GL_MODELVIEW)
     (glViewport 0 0 Width Height) ) )

(displayPrg (glClear (| GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT)) (glLoadIdentity) (glTranslatef 0.0 0.0 -3.0) (glRotatef *AngleX 1 0 0) (glRotatef *AngleY 0 1 0) (glutSolidCube 1.0)

(glDisable GL_LIGHTING) (glColor4f 0.4 0.4 0.4 1.0) (glutWireCube 1.002) (glEnable GL_LIGHTING)

(glFlush) (glutSwapBuffers) )

(glutMainLoop)</lang>

POV-Ray

<lang POV-Ray>camera { perspective location <2.6,2.2,-4.2> look_at <0,-.5,0>

      aperture .05 blur_samples 100 variance 1/100000 focal_point <2,1,-2>}
                           

light_source{< 60,20,-20> color rgb 2}

sky_sphere { pigment{ gradient z color_map{[0 rgb 0.3][.1 rgb <.7,.8,1>][1 rgb .2]} }}

box { <0,0,0> <3,2,4>

 texture { 
   pigment{ agate }
   normal { checker }
   finish { reflection {0.20 metallic 0.2} }
 } 
 translate <-1,-.5,-2> 

}</lang>

Processing

A cuboid in Processing is created with box(). It may be styled with stroke, fill, and lighting.

<lang Processing>size(500, 500, P3D); background(0); // position translate(width/2, height/2, -width/2); rotateZ(radians(15)); rotateY(radians(-30)); rotateX(radians(-25)); // optional fill and lighting colors noStroke(); fill(192, 255, 192); pointLight(255, 255, 255, 400, -400, 400); // draw box box(200, 300, 400);</lang>

Prolog

Works with SWI-Prolog and XPCE. <lang Prolog>cuboid(D1,D2,D3) :- W is D1 * 50, H is D2 * 50, D is D3 * 50,

new(C, window(cuboid)),

% compute the size of the window Width is W + ceiling(sqrt(H * 48)) + 50, Height is H + ceiling(sqrt(H * 48)) + 50, send(C, size, new(_,size(Width,Height))),

%compute the top-left corner of the front face of the cuboid PX is 25, PY is 25 + ceiling(sqrt(H * 48)),

% colors of the faces new(C1, colour(@default, 65535, 0, 0)), new(C2, colour(@default, 0, 65535, 0)), new(C3, colour(@default, 0, 0, 65535)),

% the front face new(B1, box(W, H)), send(B1, fill_pattern, C1), send(C, display,B1, point(PX, PY)),

% the top face new(B2, hpara(point(PX,PY), W, D, C2)), send(C, display, B2),

% the left face PX1 is PX + W, new(B3, vpara(point(PX1,PY), H, D, C3)), send(C, display, B3),

send(C, open).


- pce_begin_class(hpara, path, "drawing of a horizontal parallelogram").

initialise(P, Pos, Width, Height, Color) :-> send(P, send_super, initialise), send(P, append, Pos), H is ceiling(sqrt(Height * 48)), get(Pos, x, X), get(Pos, y, Y), X1 is X + H, Y1 is Y - H, send(P, append, point(X1, Y1)), X2 is X1 + Width, send(P, append, point(X2, Y1)), X3 is X2 - H, send(P, append, point(X3, Pos?y)), send(P, append, Pos), send(P, fill_pattern, Color).

- pce_end_class.
- pce_begin_class(vpara, path, "drawing of a vertical parallelogram").

initialise(P, Pos, Height, Depth, Color) :-> send(P, send_super, initialise), send(P, append, Pos), H is ceiling(sqrt(Depth * 48)), get(Pos, x, X), get(Pos, y, Y), X1 is X + H, Y1 is Y - H, send(P, append, point(X1, Y1)), Y2 is Y1 + Height, send(P, append, point(X1, Y2)), Y3 is Y2 + H, send(P, append, point(X, Y3)), send(P, append, Pos), send(P, fill_pattern, Color).

- pce_end_class.</lang>
Output:
?- cuboid(2,3,4).
true.

Pure Data

Requires `Gem` <lang Pure Data>

  1. N canvas 1 51 450 300 10;
  2. X obj 66 67 gemwin;
  3. X obj 239 148 cuboid 2 3 4;
  4. X obj 239 46 gemhead;
  5. X obj 239 68 scale 0.3;
  6. X msg 66 45 lighting 1 \, create \, 1;
  7. X obj 61 118 gemhead;
  8. X obj 61 140 world_light;
  9. X msg 294 90 1;
  10. X obj 239 90 t a b;
  11. X obj 239 118 accumrotate;
  12. X connect 2 0 3 0;
  13. X connect 3 0 8 0;
  14. X connect 4 0 0 0;
  15. X connect 5 0 6 0;
  16. X connect 7 0 9 1;
  17. X connect 7 0 9 2;
  18. X connect 7 0 9 3;
  19. X connect 8 0 9 0;
  20. X connect 8 1 7 0;
  21. X connect 9 0 1 0;

</lang> Displays a rotating cuboid.


File:PureData-cuboid.png

PureBasic

Using generic PureBasic 2D-library. <lang PureBasic>Procedure Draw_a_Cuboid(Window, X,Y,Z)

 w=WindowWidth(Window)
 h=WindowHeight(Window)
 diag.f=1.9
 If Not (w And h): ProcedureReturn: EndIf
 xscale.f = w/(x+z/diag)*0.98
 yscale.f = h/(y+z/diag)*0.98
 If xscale<yscale
   Scale.f = xscale
 Else
   Scale = yscale
 EndIf
 x*Scale: Y*Scale: Z*Scale
 CreateImage(0,w,h)
 If StartDrawing(ImageOutput(0))
   c= RGB(250, 40, 5)
   
   ;- Calculate the cones in the Cuboid
   xk = w/50     : yk = h/50
   x0 = Z/2 + xk : y0 = yk
   x1 = x0 + X   : y1 = y0
   x2 = xk       : y2 = y0 + Z/2
   x3 = x2 + X   : y3 = y2
   x4 = x2       : y4 = y2 + Y
   x5 = x4 + X   : y5 = y4
   x6 = x5 + Z/2 : y6 = y5 - Z/2
   
   ;- Draw it
   LineXY(x0,y0,x1,y1,c)
   LineXY(x0,y0,x2,y2,c)
   LineXY(x2,y2,x3,y3,c)
   LineXY(x1,y1,x3,y3,c)
   LineXY(x2,y2,x4,y4,c)
   LineXY(x4,y4,x5,y5,c)
   LineXY(x5,y5,x4,y4,c)
   LineXY(x5,y5,x6,y6,c)
   LineXY(x5,y5,x3,y3,c)
   LineXY(x6,y6,x1,y1,c)
   
   ;- Fill the areas
   FillArea(x,y,-1,RGB(255, 0, 0))
   FillArea(x,y-z/2,-1,RGB(0, 0, 255))
   FillArea(x+z/2,y,-1,RGB(0, 255, 0))
   StopDrawing()
 EndIf
 ;- Update the graphic
 ImageGadget(0,0,0,w,h,ImageID(0))

EndProcedure

  1. WFlags = #PB_Window_SystemMenu|#PB_Window_SizeGadget
  2. title = "PureBasic Cuboid"

MyWin = OpenWindow(#PB_Any, 0, 0, 200, 250, #title, #WFlags)

Repeat

 WEvent = WaitWindowEvent()
 If WEvent = #PB_Event_SizeWindow
   Draw_a_Cuboid(MyWin, 2, 3, 4)
 EndIf

Until WEvent = #PB_Event_CloseWindow

- Save the image?

UsePNGImageEncoder() respons = MessageRequester("Question","Save the image?",#PB_MessageRequester_YesNo) If respons=#PB_MessageRequester_Yes

 SaveImage(0, SaveFileRequester("","","",0),#PB_ImagePlugin_PNG,9)

EndIf</lang>

Python

Ascii-Art

<lang python>def _pr(t, x, y, z):

   txt = '\n'.join(.join(t[(n,m)] for n in range(3+x+z)).rstrip()
                   for m in reversed(range(3+y+z)))
   return txt

def cuboid(x,y,z):

   t = {(n,m):' ' for n in range(3+x+z) for m in range(3+y+z)}
   xrow = ['+'] + ['%i' % (i % 10) for i in range(x)] + ['+']
   for i,ch in enumerate(xrow):
       t[(i,0)] = t[(i,1+y)] = t[(1+z+i,2+y+z)] = ch
   if _debug: print(_pr(t, x, y, z))
   ycol = ['+'] + ['%i' % (j % 10) for j in range(y)] + ['+']
   for j,ch in enumerate(ycol):
       t[(0,j)] = t[(x+1,j)] = t[(2+x+z,1+z+j)] = ch
   zdepth = ['+'] + ['%i' % (k % 10) for k in range(z)] + ['+']
   if _debug: print(_pr(t, x, y, z))
   for k,ch in enumerate(zdepth):
       t[(k,1+y+k)] = t[(1+x+k,1+y+k)] = t[(1+x+k,k)] = ch
   return _pr(t, x, y, z)


_debug = False if __name__ == '__main__':

   for dim in ((2,3,4), (3,4,2), (4,2,3)):
       print("CUBOID%r" % (dim,), cuboid(*dim), sep='\n')</lang>
Output:
CUBOID(2, 3, 4)
     +01+
    3  32
   2  2 1
  1  1  0
 0  0   +
+01+   3
2  2  2
1  1 1
0  00
+01+
CUBOID(3, 4, 2)
   +012+
  1   13
 0   0 2
+012+  1
3   3  0
2   2  +
1   1 1
0   00
+012+
CUBOID(4, 2, 3)
    +0123+
   2    21
  1    1 0
 0    0  +
+0123+  2
1    1 1
0    00
+0123+

Library: VPython

The cuboid (otherwise known as a "box" :)

Works with: Python version 2.7.5

Short version

<lang python>from visual import * mybox = box(pos=(0,0,0), length=4, height=2, width=3, axis=(-0.1,-0.1,0.1) ) scene.title = "VPython: cuboid"</lang>

Cuboid viewer

This has a lot of extras around the cuboid, so you can rotate the box (stepwise and continous), change the background, color, transparancy, material, show infos about scene and object, plus a selfrunning demo-mode that cycles thru everything. <lang python> from __future__ import print_function, division from visual import * import itertools

title = "VPython: Draw a cuboid" scene.title = title print( "%s\n" % title )

msg = """ Drag with right mousebutton to rotate view. Drag up+down with middle mousebutton to zoom. Left mouseclick to show info.

Press x,X, y,Y, z,Z to rotate the box in single steps. Press b, c,o,m to change background, color, opacity, material. Press r,R to rotate, d,a for demo, automatic, space to stop. Press h to show this help, ESC or q to quit. """

  1. ...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+...
    1. Rotate one step per keypress:

def rotX(obj, a) :

   obj.rotate( angle=a, axis=(1,0,0) )

def rotY(obj, a) :

   obj.rotate( angle=a, axis=(0,1,0) )

def rotZ(obj, a) :

   obj.rotate( angle=a, axis=(0,0,1) )
    1. Selection of background-colors:

bg_list = [color.gray(0.2), color.gray(0.4), color.gray(0.7), color.gray(0.9)] bg = itertools.cycle(bg_list) def backgr() :

   b = next(bg)
   print("BackgroundColor=",b)
   scene.background = b
    1. Selection of colors:

col_list = [color.white, color.red, color.orange, color.yellow,

           color.green, color.blue, color.cyan,   color.magenta, 
           color.black]

col = itertools.cycle(col_list)

  1. c = col.next()
  2. c = next(col)

def paint(obj) :

   c = next(col)
   print("Color=",c)
   obj.color = c
    1. Selection of opacity / transparancy :

opa_list = [1.0, 0.7, 0.5, 0.2] opa = itertools.cycle(opa_list) def solid(obj) :

   o = next(opa)
   print("opacity =",o)
   obj.opacity = o
    1. Selection of materials:

mName_list = ["None",

             "wood",
             "rough",
             "bricks",
             "glass",
             "earth",
             "plastic",
             "ice",
             "diffuse",
             "marble" ]

mat_list = [ None,

             materials.wood,
             materials.rough,
             materials.bricks,
             materials.glass,
             materials.earth,
             materials.plastic,
             materials.ice,
             materials.diffuse,
             materials.marble ]

mName = itertools.cycle(mName_list) mat = itertools.cycle(mat_list) def surface(obj) :

   mM = next(mat)
   mN = next(mName)
   print("Material:", mN)
   obj.material = mM
   obj.mat      = mN
    1. Selection for rotation-angle & axis :

rotAng_list = [ 0.0, 0.005, 0.0, -0.005 ] rotDir_list = [ (1,0,0), (0,1,0), (0,0,1) ]

rotAng = itertools.cycle(rotAng_list) rotDir = itertools.cycle(rotDir_list)

rotAn = next(rotAng) # rotAn = 0.005 rotAx = next(rotDir) # rotAx = (1,0,0)

def rotAngle() :

   global rotAn
   rotAn = next(rotAng)
   print("RotateAngle=",rotAn)

def rotAxis() :

   global rotAx
   rotAx = next(rotDir)
   print("RotateAxis=",rotAx)
    1. List of keypresses for demo:
  1. demoC_list = [ "h", "c", "a", "o", "m", "b" ]

demoCmd_list = "rcbr"+"robr"+"rmR_r?" demoCmd = itertools.cycle(demoCmd_list) def demoStep() :

   k = next(demoCmd)
   print("Demo:",k)
   cmd(k)
  1. ...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+...

def objCount():

   n=0
   for obj in scene.objects:
       n=n+1
   return n
           

def objInfo(obj) :

   print( "\nObject:", obj )
   print( "Pos:",  obj.pos,   "Size:", obj.size )
   print( "Axis:", obj.axis,  "Up:",   obj.up )
   print( "Color", obj.color, obj.opacity )
   print( "Mat:",  obj.mat,   obj.material )

def sceneInfo(sc) :

   print( "\nScene:",  sc )
   print( ".width x height:",   sc.width, "x", sc.height )
   print( ".range:",   sc.range, ".scale:", sc.scale )
   print( ".center:",  sc.center )    # Camera
   print( ".forward:", sc.forward, ".fov:", sc.fov )
   print( "Mouse:",    sc.mouse.camera, "ray:", sc.mouse.ray )
   print( ".ambient:", sc.ambient )
   print( "Lights:",   sc.lights  )    # distant_light
   print( "objects:", objCount(), scene.objects )
   
  1. ...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+...

scene.width = 600 scene.height = 400 scene.range = 4

  1. scene.autocenter = True
  2. scene.background = color.gray(0.2)

scene.background = next(bg)

autoDemo = -1

print( msg )


    1. Create cuboid (aka "box") :
  1. c = box() # using default-values --> cube
  2. c = box(pos=(0,0,0), length=4, height=2, width=3, axis=(-0.1,-0.1,0.1) )
    1. c = box(pos =( 0.0, 0.0, 0.0 ),
    2. size=( 4, 2, 3 ), # L,H,W
    3. axis=( 1.0, 0.0, 0.0 ),
    4. up =( 0.0, 1.0, 0.0 ),
    5. color = color.orange,
    6. opacity = 1.0,
    7. material= materials.marble
    8. )

c = box(pos =( 0.0, 0.0, 0.0 ),

        size=( 4, 2, 3 ),            # L,H,W
        axis=( 1.0, 0.0, 0.0 ),
        up  =( 0.0, 1.0, 0.0 )
        )

print("Box:", c) paint(c) # c.color = color.red solid(c) # c.opacity = 1.0 surface(c) # c.material = materials.marble

rotX(c,0.4) # rotate box, to bring three faces into view rotY(c,0.6)

  1. sceneInfo(scene)
  2. objInfo(c)

print("\nPress 'a' to start auto-running demo.")

  1. ...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+...


    1. Processing of input:

cCount = 0 def click():

   global cCount
   cCount=cCount+1
   sceneInfo(scene)
   objInfo(c)

scene.bind( 'click', click )

def keyInput():

   key = scene.kb.getkey()
   print( 'Key: "%s"' % key )
   if ( (key == 'esc') or (key == 'q') ) :
       print( "Bye!" )
       exit(0)
   else :
       cmd(key)

scene.bind('keydown', keyInput)

def cmd(key):

   global autoDemo
   if (key == 'h') :  print( msg )
   if (key == '?') :  print( msg )
   if (key == 's') :  sceneInfo(scene)
   if (key == 'i') :  objInfo(c)
   if (key == 'x') :  rotX(c, 0.1)
   if (key == 'X') :  rotX(c,-0.1)
   if (key == 'y') :  rotY(c, 0.1)
   if (key == 'Y') :  rotY(c,-0.1)
   if (key == 'z') :  rotZ(c, 0.1)
   if (key == 'Z') :  rotZ(c,-0.1)
   if (key == 'c') :  paint(c)
   if (key == 'o') :  solid(c)
   if (key == 'm') :  surface(c)
   if (key == 'b') :  backgr()
   if (key == 'r') :  rotAngle()
   if (key == 'R') :  rotAxis()
   if (key == 'd') :  demoStep()
   if (key == 'a') :  autoDemo = -autoDemo
   if (key == 'A') :  autoDemo = -autoDemo
   if (key == ' ') :  stop()

def stop() :

   global autoDemo, rotAn
   autoDemo = -1
   while rotAn <> 0 :
     rotAngle() 
   print("**Stop**")
     

r=100 t=0 while True: # Animation-loop

   rate(50)
   t = t+1
   if rotAn != 0 :
       c.rotate( angle=rotAn, axis=rotAx )
   if t>=r :
       t=0
       if autoDemo>0 :
           demoStep()

</lang>

Racket

<lang Racket>#lang racket/gui (require sgl/gl)

Macro to delimit and automatically end glBegin - glEnd contexts.

(define-syntax-rule (gl-begin-end Vertex-Mode statement ...)

 (let () (glBegin Vertex-Mode) statement ... (glEnd)))

(define (resize w h)

 (glViewport 0 0 w h))

(define (draw-opengl x y z)

 (glClearColor 0.0 0.0 0.0 0.0)
 (glEnable GL_DEPTH_TEST)
 (glClear GL_COLOR_BUFFER_BIT)
 (glClear GL_DEPTH_BUFFER_BIT)
 (define max-axis (add1 (max x y z)))
 (glMatrixMode GL_PROJECTION)
 (glLoadIdentity)
 (glOrtho (/ (- max-axis) 2) max-axis (/ (- max-axis) 2) max-axis (/ (- max-axis) 2) max-axis)
 (glMatrixMode GL_MODELVIEW)
 (glLoadIdentity)
 (glRotatef -45 1.0 0.0 0.0)
 (glRotatef 45 0.0 1.0 0.0)
 (gl-begin-end GL_QUADS
               (glColor3f 0 0 1)
               (glVertex3d x 0.0 z)
               (glVertex3d x y z)
               (glVertex3d x y 0.0)
               (glVertex3d x 0.0 0.0))
 (gl-begin-end GL_QUADS
               (glColor3f 1 0 0)
               (glVertex3d x 0.0 0.0)
               (glVertex3d x y 0.0)
               (glVertex3d 0.0 y 0.0)
               (glVertex3d 0.0 0.0 0.0)) 
 (gl-begin-end GL_QUADS
               (glColor3f 0 1 0)
               (glVertex3d x y 0.0)
               (glVertex3d x y z)
               (glVertex3d 0.0 y z)
               (glVertex3d 0.0 y 0.0)))

(define my-canvas%

 (class* canvas% ()
   (inherit with-gl-context swap-gl-buffers)
   (init-field (x 2) (y 3) (z 4))
   (define/override (on-paint)
     (with-gl-context
       (lambda ()
         (draw-opengl x y z)
         (swap-gl-buffers))))
   (define/override (on-size width height)
     (with-gl-context
       (lambda ()
         (resize width height))))
   (super-instantiate () (style '(gl)))))

(define win (new frame% (label "Racket Draw a cuboid") (min-width 300) (min-height 300))) (define gl (new my-canvas% (parent win) (x 2) (y 3) (z 4)))

(send win show #t)</lang>

Raku

(formerly Perl 6)

Works with: moar version 2015-11-27

<lang perl6>sub braille-graphics (%a) {

   my ($ylo, $yhi, $xlo, $xhi);
   for %a.keys -> $y {

$ylo min= +$y; $yhi max= +$y; for %a{$y}.keys -> $x { $xlo min= +$x; $xhi max= +$x; }

   }
   for $ylo, $ylo + 4 ...^ * > $yhi -> \y {

for $xlo, $xlo + 2 ...^ * > $xhi -> \x { my $cell = 0x2800; $cell += 1 if %a{y + 0}{x + 0}; $cell += 2 if %a{y + 1}{x + 0}; $cell += 4 if %a{y + 2}{x + 0}; $cell += 8 if %a{y + 0}{x + 1}; $cell += 16 if %a{y + 1}{x + 1}; $cell += 32 if %a{y + 2}{x + 1}; $cell += 64 if %a{y + 3}{x + 0}; $cell += 128 if %a{y + 3}{x + 1}; print chr($cell); } print "\n";

   }

}

sub cuboid ( [$x, $y, $z] ) {

   my \x = $x * 4;
   my \y = $y * 4;
   my \z = $z * 2;
   my %t;
   sub horz ($X, $Y) { %t{$Y     }{$X + $_} = True for 0 .. x }
   sub vert ($X, $Y) { %t{$Y + $_}{$X     } = True for 0 .. y }
   sub diag ($X, $Y) { %t{$Y - $_}{$X + $_} = True for 0 .. z }

   horz(0, z); horz(z, 0); horz(  0, z+y);
   vert(0, z); vert(x, z); vert(z+x,   0);
   diag(0, z); diag(x, z); diag(  x, z+y);

   say "[$x, $y, $z]";
   braille-graphics %t;

}

cuboid $_ for [2,3,4], [3,4,2], [4,2,3], [1,1,1], [8,1,1], [1,8,1], [1,1,8];</lang>

Output:

Retro

<lang Retro>3 elements d h w

spaces ( n- ) &space times ;
--- ( - ) '+ putc @w 2 * [ '- putc ] times '+ putc ;
? ( n- ) @h <> [ '| ] [ '+ ] if ;
slice ( n- ) '/ putc @w 2 * spaces '/ putc @d swap - dup spaces ? putc cr ;
|...|/ ( - ) @h [ '| putc @w 2 * spaces '| putc 1- spaces '/ putc cr ] iterd ;
face ( - )
  ---    @w 1+ spaces '/ putc cr
 |...|/
  ---    cr ;
cuboid ( whd- )
 !d !h !w cr
 @d 1+ spaces --- cr
 @d [ dup spaces slice ] iterd
 face ;

2 3 4 cuboid</lang>

Output:
     +----+
    /    /|
   /    / |
  /    /  |
 /    /   +
+----+   / 
|    |  /  
|    | /   
|    |/    
+----+     

REXX

<lang rexx>/*REXX program displays a cuboid (dimensions, if specified, must be positive integers).*/ parse arg x y z indent . /*x, y, z: dimensions and indentation.*/ x=p(x 2); y=p(y 3); z=p(z 4); in=p(indent 0) /*use the defaults if not specified. */ pad=left(, in) /*indentation must be non-negative. */

                       call show  y+2  ,        ,     "+-"
      do j=1  for y;   call show  y-j+2,     j-1,     "/ |"     ;       end  /*j*/
                       call show       ,     y  ,     "+-|"
      do z-1;          call show       ,     y  ,     "| |"     ;       end  /*z-1*/
                       call show       ,     y  ,     "| +"
      do j=1  for y;   call show       ,     y-j,     "| /"     ;       end  /*j*/
                       call show       ,        ,     "+-"

exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ p: return word( arg(1), 1) /*pick the first number or word in list*/ /*──────────────────────────────────────────────────────────────────────────────────────*/ show: parse arg #,$,a 2 b 3 c 4 /*get the arguments (or parts thereof).*/

      say pad || right(a, p(# 1) )copies(b, 4*x)a || right(c, p($ 0) + 1);         return</lang>

output   when using the input of:   2   3   4   35

                                       +--------+
                                      /        /|
                                     /        / |
                                    /        /  |
                                   +--------+   |
                                   |        |   |
                                   |        |   |
                                   |        |   |
                                   |        |   +
                                   |        |  /
                                   |        | /
                                   |        |/
                                   +--------+

output   when using the input of:   1   1   1

  +----+
 /    /|
+----+ |
|    | +
|    |/
+----+

output   when using the input of:   6   2   1   25

                            +------------------------+
                           /                        /|
                          /                        / |
                         +------------------------+  |
                         |                        |  +
                         |                        | /
                         |                        |/
                         +------------------------+

Ring

<lang ring>

  1. Project : Draw a cuboid

load "guilib.ring"

paint = null

new qapp

       {
       win1 = new qwidget() {
                 setwindowtitle("Draw a cuboid")
                 setgeometry(100,100,500,600)
                 label1 = new qlabel(win1) {
                             setgeometry(10,10,400,400)
                             settext("")
                 }
                 new qpushbutton(win1) {
                         setgeometry(150,500,100,30)
                         settext("draw")
                         setclickevent("draw()")
                 }
                 show()
       }
       exec()
       }

func draw

       p1 = new qpicture()
              color = new qcolor() {
              setrgb(0,0,255,255)
       }
       pen = new qpen() {
                setcolor(color)
                setwidth(1)
       }
       paint = new qpainter() {
                 begin(p1)
                 setpen(pen)
       color = new qcolor()
       color.setrgb(255,0,0,255)
       mybrush = new qbrush() {setstyle(1) setcolor(color)}
       setbrush(mybrush)
       paint.drawPolygon([[200,200],[300,200],[300,100],[200,100]], 0)
       color = new qcolor()
       color.setrgb(0,255,0,255)
       mybrush = new qbrush() {setstyle(1) setcolor(color)}
       setbrush(mybrush)
       paint.drawPolygon([[200,100],[250,50],[350,50],[300,100]], 0)
       color = new qcolor()
       color.setrgb(0, 0, 255,255)
       mybrush = new qbrush() {setstyle(1) setcolor(color)}
       setbrush(mybrush)
       paint.drawPolygon([[350,50],[350,150],[300,200],[300,100]], 0)
       endpaint()
       }
       label1 { setpicture(p1) show() }
       return

</lang> Output:

https://www.dropbox.com/s/bdew8ihhm0c79sd/DrawCuboid.jpg?dl=0

Ruby

<lang ruby>X, Y, Z = 6, 2, 3 DIR = {"-" => [1,0], "|" => [0,1], "/" => [1,1]}

def cuboid(nx, ny, nz)

 puts "cuboid %d %d %d:" % [nx, ny, nz]
 x, y, z = X*nx, Y*ny, Z*nz
 area = Array.new(y+z+1){" " * (x+y+1)}
 draw_line = lambda do |n, sx, sy, c|
   dx, dy = DIR[c]
   (n+1).times do |i|
     xi, yi = sx+i*dx, sy+i*dy
     area[yi][xi] = (area[yi][xi]==" " ? c : "+")
   end
 end
 nz    .times {|i| draw_line[x,     0,   Z*i, "-"]}
 (ny+1).times {|i| draw_line[x,   Y*i, z+Y*i, "-"]}
 nx    .times {|i| draw_line[z,   X*i,     0, "|"]}
 (ny+1).times {|i| draw_line[z, x+Y*i,   Y*i, "|"]}
 nz    .times {|i| draw_line[y,     x,   Z*i, "/"]}
 (nx+1).times {|i| draw_line[y,   X*i,     z, "/"]}
 puts area.reverse

end

cuboid(2, 3, 4) cuboid(1, 1, 1) cuboid(6, 2, 1) cuboid(2, 4, 1)</lang>

Output:
cuboid 2 3 4:
      +-----+-----+
     /     /     /|
    +-----+-----+ |
   /     /     /| +
  +-----+-----+ |/|
 /     /     /| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/ 
|     |     |/| +  
+-----+-----+ |/   
|     |     | +    
|     |     |/     
+-----+-----+      
cuboid 1 1 1:
  +-----+
 /     /|
+-----+ |
|     | +
|     |/ 
+-----+  
cuboid 6 2 1:
    +-----+-----+-----+-----+-----+-----+
   /     /     /     /     /     /     /|
  +-----+-----+-----+-----+-----+-----+ |
 /     /     /     /     /     /     /| +
+-----+-----+-----+-----+-----+-----+ |/ 
|     |     |     |     |     |     | +  
|     |     |     |     |     |     |/   
+-----+-----+-----+-----+-----+-----+    
cuboid 2 4 1:
        +-----+-----+
       /     /     /|
      +-----+-----+ |
     /     /     /| +
    +-----+-----+ |/ 
   /     /     /| +  
  +-----+-----+ |/   
 /     /     /| +    
+-----+-----+ |/     
|     |     | +      
|     |     |/       
+-----+-----+        

Scala

Java Swing Interoperability

<lang Scala>import java.awt._ import java.awt.event.{MouseAdapter, MouseEvent}

import javax.swing._

import scala.math.{Pi, cos, sin}

object Cuboid extends App {

 SwingUtilities.invokeLater(() => {
   class Cuboid extends JPanel {
     private val nodes: Array[Array[Double]] =
       Array(Array(-1, -1, -1), Array(-1, -1, 1), Array(-1, 1, -1), Array(-1, 1, 1),
         Array(1, -1, -1), Array(1, -1, 1), Array(1, 1, -1), Array(1, 1, 1))
     private var mouseX, prevMouseX, mouseY, prevMouseY: Int = _
     private def edges =
       Seq(Seq(0, 1), Seq(1, 3), Seq(3, 2), Seq(2, 0),
         Seq(4, 5), Seq(5, 7), Seq(7, 6), Seq(6, 4),
         Seq(0, 4), Seq(1, 5), Seq(2, 6), Seq(3, 7))
     override def paintComponent(gg: Graphics): Unit = {
       val g = gg.asInstanceOf[Graphics2D]
       def drawCube(g: Graphics2D): Unit = {
         g.translate(getWidth / 2, getHeight / 2)
         for (edge <- edges) {
           g.drawLine(nodes(edge.head)(0).round.toInt, nodes(edge.head)(1).round.toInt,
             nodes(edge(1))(0).round.toInt, nodes(edge(1))(1).round.toInt)
         }
         for (node <- nodes) g.fillOval(node(0).round.toInt - 4, node(1).round.toInt - 4, 8, 8)
       }
       super.paintComponent(gg)
       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
       drawCube(g)
     }
     private def scale(sx: Double, sy: Double, sz: Double): Unit = {
       for (node <- nodes) {
         node(0) *= sx
         node(1) *= sy
         node(2) *= sz
       }
     }
     private def rotateCube(angleX: Double, angleY: Double): Unit = {
       val (sinX, cosX, sinY, cosY) = (sin(angleX), cos(angleX), sin(angleY), cos(angleY))
       for (node <- nodes) {
         val (x, y, z) = (node.head, node(1), node(2))
         node(0) = x * cosX - z * sinX
         node(2) = z * cosX + x * sinX
         node(1) = y * cosY - node(2) * sinY
         node(2) = node(2) * cosY + y * sinY
       }
     }
     addMouseListener(new MouseAdapter() {
       override def mousePressed(e: MouseEvent): Unit = {
         mouseX = e.getX
         mouseY = e.getY
       }
     })
     addMouseMotionListener(new MouseAdapter() {
       override def mouseDragged(e: MouseEvent): Unit = {
         prevMouseX = mouseX
         prevMouseY = mouseY
         mouseX = e.getX
         mouseY = e.getY
         rotateCube((mouseX - prevMouseX) * 0.01, (mouseY - prevMouseY) * 0.01)
         repaint()
       }
     })
     scale(80, 120, 160)
     rotateCube(Pi / 5, Pi / 9)
     setPreferredSize(new Dimension(640, 640))
     setBackground(Color.white)
   }
   new JFrame("Cuboid") {
     add(new Cuboid, BorderLayout.CENTER)
     pack()
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
     setLocationRelativeTo(null)
     setResizable(false)
     setVisible(true)
   }
 })

}</lang>

Sidef

Translation of: Ruby

<lang ruby>const dirs = Hash("-" => [1,0], "|" => [0,1], "/" => [1,1])   func cuboid(nx, ny, nz) {

 say("cuboid %d %d %d:" % [nx, ny, nz])
 var(x, y, z) = (8*nx, 2*ny, 4*nz)
 var area = []
 var line = func(n, sx, sy, c) {
   var(dx, dy) = dirs{c}...
   for i (0..n) {
     var (xi, yi) = (sx + i*dx, sy + i*dy)
     area[yi] \\= [" "]*(x+y+1)
     area[yi][xi] = (area[yi][xi] == " " ? c : '+')
   }
 }

 

 0 .. nz-1 -> each {|i| line(x,       0,     4*i, "-") }
 0 .. ny   -> each {|i| line(x,     2*i, z + 2*i, "-") }
 0 .. nx-1 -> each {|i| line(z,     8*i,       0, "|") }
 0 .. ny   -> each {|i| line(z, x + 2*i,     2*i, "|") }
 0 .. nz-1 -> each {|i| line(y,       x,     4*i, "/") }
 0 .. nx   -> each {|i| line(y,     8*i,       z, "/") }

 

 area.reverse.each { |line|
    say line.join()
 }

}   cuboid(2, 3, 4) cuboid(1, 1, 1) cuboid(6, 2, 1) cuboid(2, 4, 1)</lang>

A faster approach: <lang ruby>func cuboid (x=1,y=1,z=1,s=' ',c='+',h='-',v='|',d='/') {

   say("cuboid %d %d %d:" % (x, y, z))
   ' ' * z+1 + c + h*x + c -> say
   { |i|
       ' ' * (z - i + 1) + d + s*x + d +
             (s * (i - (i > y ? i-y : 1))) +
             (i - 1 == y ? c : (i > y ? d : v)) -> say
   }.for(1..z)
   c + h*x + c + (s * (z < y ? z : y) +
       (z < y ? v : (z == y ? c : d))) -> say
   { |i|
       v + s*x + v + (z > y
           ? (i >= z ? (s*x + c) : (s * y-i + d))
           : (y - i > z
               ? (s * z + v)
               : (s * y-i + (y-i == z ? c : d))
              )
       ) -> say;
   }.for(1..y)
   c + h*x + c -> say

}

cuboid(2, 3, 4) cuboid(1, 1, 1) cuboid(6, 2, 1) cuboid(2, 4, 1)</lang>

Output:
cuboid 2 3 4:
     +--+
    /  /|
   /  / |
  /  /  |
 /  /   +
+--+   /
|  |  /
|  | /
|  |/
+--+
cuboid 1 1 1:
  +-+
 / /|
+-+ +
| |/
+-+
cuboid 6 2 1:
  +------+
 /      /|
+------+ |
|      | +
|      |/
+------+
cuboid 2 4 1:
  +--+
 /  /|
+--+ |
|  | |
|  | |
|  | +
|  |/
+--+

Tcl

Library: Tk
Library: Tcllib (Package: math::linearalgebra)
Library: Tcllib (Package: math::constants)

<lang tcl>package require Tcl 8.5 package require Tk package require math::linearalgebra package require math::constants

  1. Helper for constructing a rectangular face in 3D

proc face {px1 py1 pz1 px2 py2 pz2 px3 py3 pz3 px4 py4 pz4 color} {

   set centroidX [expr {($px1+$px2+$px3+$px4)/4.0}]
   set centroidY [expr {($py1+$py2+$py3+$py4)/4.0}]
   set centroidZ [expr {($pz1+$pz2+$pz3+$pz4)/4.0}]
   list [list \

[list [expr {double($px1)}] [expr {double($py1)}] [expr {double($pz1)}]] \ [list [expr {double($px2)}] [expr {double($py2)}] [expr {double($pz2)}]] \ [list [expr {double($px3)}] [expr {double($py3)}] [expr {double($pz3)}]] \ [list [expr {double($px4)}] [expr {double($py4)}] [expr {double($pz4)}]]] \ [list $centroidX $centroidY $centroidZ] \ $color }

  1. How to make a cuboid of given size at the origin

proc makeCuboid {size} {

   lassign $size x y z
   list \

[face 0 0 0 0 $y 0 $x $y 0 $x 0 0 "#800000"] \ [face 0 0 0 0 $y 0 0 $y $z 0 0 $z "#ff8080"] \ [face 0 0 0 $x 0 0 $x 0 $z 0 0 $z "#000080"] \ [face $x 0 0 $x $y 0 $x $y $z $x 0 $z "#008000"] \ [face 0 $y 0 $x $y 0 $x $y $z 0 $y $z "#80ff80"] \ [face 0 0 $z $x 0 $z $x $y $z 0 $y $z "#8080ff"] }

  1. Project a shape onto a surface (Tk canvas); assumes that the shape's faces
  2. are simple and non-intersecting (i.e., it sorts by centroid z-order).

proc drawShape {surface shape} {

   global projection
   lassign $projection pmat poff
   lassign $poff px py pz
   foreach side $shape {

lassign $side points centroid color set pc [::math::linearalgebra::matmul $pmat $centroid] lappend sorting [list [expr {[lindex $pc 2]+$pz}] $points $color]

   }
   foreach side [lsort -real -decreasing -index 0 $sorting] {

lassign $side sortCriterion points color set plotpoints {} foreach p $points { set p [::math::linearalgebra::matmul $pmat $p] lappend plotpoints \ [expr {[lindex $p 0]+$px}] [expr {[lindex $p 1]+$py}] } $surface create poly $plotpoints -outline {} -fill $color

   }

}

  1. How to construct the projection transform.
  2. This is instead of using a hokey hard-coded version

namespace eval transform {

   namespace import ::math::linearalgebra::*
   ::math::constants::constants pi
   proc make {angle scale offset} {

variable pi set c [expr {cos($angle*$pi/180)}] set s [expr {sin($angle*$pi/180)}] set ms [expr {-$s}] set rotX [list {1.0 0.0 0.0} [list 0.0 $c $ms] [list 0.0 $s $c]] set rotY [list [list $c 0.0 $s] {0.0 1.0 0.0} [list $ms 0.0 $c]] set rotZ [list [list $c $s 0.0] [list $ms $c 0.0] {0.0 0.0 1.0}] set mat [scale $scale [mkIdentity 3]] set mat [matmul [matmul [matmul $mat $rotX] $rotY] $rotZ] return [list $mat $offset]

   }

}

      1. End of definitions
  1. Put the pieces together

pack [canvas .c -width 400 -height 400] set cuboid [makeCuboid {2 3 4}] set projection [transform::make 15 50 {100 100 100}] drawShape .c $cuboid</lang> Output (cropped)

This becomes more engaging if the drawing is animated with a final driver piece like this (the definitions part of the code is identical to above): <lang tcl>pack [canvas .c -width 400 -height 400] set cuboid [makeCuboid {2 3 4}] wm protocol . WM_DELETE_WINDOW { exit } while 1 {

   incr i
   .c delete all
   set projection [transform::make $i 40 {150 150 100}]
   drawShape .c $cuboid
   update
   after 50

}</lang>

VBScript

Translation of: Ruby

<lang vb>x = 6 : y = 2 : z = 3

Sub cuboid(nx, ny, nz)

  WScript.StdOut.WriteLine "Cuboid " & nx & " " & ny & " " & nz & ":"
  lx = X * nx : ly = y * ny : lz = z * nz
  'define the array
  Dim area(): ReDim area(ly+lz, lx+ly)
  For i = 0 to ly+lz
     For j = 0 to lx+ly : area(i,j) = " " : Next
  Next
  'drawing lines
  For i = 0 to nz-1 : drawLine area, lx,      0,    Z*i, "-" : Next
  For i = 0 to ny   : drawLine area, lx,    y*i, lz+y*i, "-" : Next
  For i = 0 to nx-1 : drawLine area, lz,    x*i,      0, "|" : Next
  For i = 0 to ny   : drawLine area, lz, lx+y*i,    y*i, "|" : Next
  For i = 0 to nz-1 : drawLine area, ly,     lx,    z*i, "/" : Next
  For i = 0 to nx   : drawLine area, ly,    x*i,     lz, "/" : Next
  'output the cuboid (in reverse)
  For i = UBound(area,1) to 0 Step -1
     linOut = ""
     For j = 0 to UBound(area,2) : linOut = linOut & area(i,j) : Next
     WScript.StdOut.WriteLine linOut
  Next

End Sub

Sub drawLine(arr, n, sx, sy, c)

  Select Case c
     Case "-"
        dx = 1 : dy = 0
     Case "|"
        dx = 0 : dy = 1
     Case "/"
        dx = 1 : dy = 1
  End Select
  For i = 0 to n
     xi = sx + (i * dx) : yi = sy + (i * dy)
     If arr(yi, xi) = " " Then
        arr(yi, xi) = c
     Else
        arr(yi, xi) = "+"
     End If
  Next

End Sub

cuboid 2,3,4</lang>

Output:
Cuboid 2 3 4:
      +-----+-----+
     /     /     /|
    +-----+-----+ |
   /     /     /| +
  +-----+-----+ |/|
 /     /     /| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/
|     |     |/| +
+-----+-----+ |/
|     |     | +
|     |     |/
+-----+-----+

Wren

Translation of: Go
Library: Wren-fmt

<lang ecmascript>import "/fmt" for Fmt

var cubLine = Fn.new { |n, dx, dy, cde|

   Fmt.write("$*s", n + 1, cde[0])
   for (d in 9*dx - 1...0) System.write(cde[1])
   System.write(cde[0])
   Fmt.print("$*s", dy + 1, cde[2..-1])

}

var cuboid = Fn.new { |dx, dy, dz|

   Fmt.print("cuboid $d $d $d:", dx, dy, dz)
   cubLine.call(dy+1, dx, 0, "+-")
   for (i in 1..dy) cubLine.call(dy-i+1, dx, i-1, "/ |")
   cubLine.call(0, dx, dy, "+-|")
   for (i in 4*dz - dy - 2...0) cubLine.call(0, dx, dy, "| |")
   cubLine.call(0, dx, dy, "| +")
   for (i in 1..dy) cubLine.call(0, dx, dy-i, "| /")
   cubLine.call(0, dx, 0, "+-\n")

}

cuboid.call(2, 3, 4) cuboid.call(1, 1, 1) cuboid.call(6, 2, 1)</lang>

Output:
cuboid 2 3 4:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

cuboid 1 1 1:
  +--------+ 
 /        /|
+--------+ |
|        | |
|        | +
|        |/
+--------+

cuboid 6 2 1:
   +-----------------------------------------------------+ 
  /                                                     /|
 /                                                     / |
+-----------------------------------------------------+  |
|                                                     |  +
|                                                     | /
|                                                     |/
+-----------------------------------------------------+

X86 Assembly

Sixty bytes does it. <lang asm> 1 ;Assemble with: tasm, tlink /t

     2     0000                                 .model  tiny
     3     0000                                 .code
     4                                          .386
     5                                          org     100h
     6                                  ;assume: ax=0000h, bx=0000h, cx=00ff, and
     7                                  ; direction bit is clear (so di increments)
     8                                                                  ;                  ____
     9           =0050                  X0      equ     80              ;                 /   /|
    10           =0050                  Y0      equ     80              ;                /   / |
    11           =0050                  wide    equ     2*40            ;         X0,Y0 +---+  |
    12           =0064                  tall    equ     3*40*200/240    ;               |   |  |
    13           =0035                  deep    equ     4*40/3          ;               |   | /
    14                                                                  ;               |___|/
    15
    16     0100  B0 13                  start:  mov     al, 13h         ;set 320x200x8 graphic screen
    17     0102  CD 10                          int     10h
    18     0104  68 A000                        push    0A000h          ;point es to graphic memory segment
    19     0107  07                             pop     es
    20
    21                                  ;Draw front of cuboid using horizontal lines
    22     0108  B3 64                          mov     bl, tall
    23     010A  BF E150                        mov     di, X0+(Y0+tall)*320 ;set pen at lower-left corner
    24     010D  B0 04                          mov     al, 4           ;use red ink
    25     010F  B1 50                  dc10:   mov     cl, wide        ;draw horizontal line
    26     0111  F3> AA                         rep     stosb           ;es:[di++], al; cx--
    27     0113  81 EF 0190                     sub     di, wide+320    ;move up to start of next line
    28     0117  4B                             dec     bx              ;at top of face?
    29     0118  75 F5                          jne     dc10            ;loop if not
    30
    31     011A  B3 35                          mov     bl, deep
    32                                  ;Draw top using horizontal lines
    33     011C  B0 02                  dc20:   mov     al, 2           ;use green ink
    34     011E  B1 50                          mov     cl, wide        ;draw horizontal line
    35     0120  F3> AA                         rep     stosb           ;es:[di++], al; cx--
    36
    37                                  ;Draw side using vertical lines
    38     0122  B0 01                          mov     al, 1           ;use blue ink
    39     0124  B1 64                          mov     cl, tall        ;draw vertical line
    40     0126  AA                     dc30:   stosb                   ;es:[di++], al
    41     0127  81 C7 013F                     add     di, 320-1       ;move down a pixel
    42     012B  E2 F9                          loop    dc30
    43
    44     012D  81 EF 7E8F                     sub     di, wide+(tall+1)*320-1 ;move to start of next top line
    45     0131  4B                             dec     bx              ;at deep limit?
    46     0132  75 E8                          jne     dc20            ;loop if not
    47
    48     0134  CD 16                          int     16h             ;wait for keystroke (ah=0)
    49     0136  B8 0003                        mov     ax, 0003h       ;restore normal text-mode screen
    50     0139  CD 10                          int     10h
    51     013B  C3                             ret                     ;return to DOS
    52
    53                                          end     start

</lang>

Output:

XPL0

<lang XPL0>include c:\cxpl\codes; \intrinsic 'code' declarations real X, Y, Z, Farthest; \arrays: 3D coordinates of vertices int I, J, K, SI, Segment; def Size=50.0, Sz=0.008, Sx=-0.013; \drawing size and tumbling speeds [X:= [-2.0, +2.0, +2.0, -2.0, -2.0, +2.0, +2.0, -2.0];

Y:= [-1.5, -1.5, +1.5, +1.5,  -1.5, -1.5, +1.5, +1.5];
Z:= [-1.0, -1.0, -1.0, -1.0,  +1.0, +1.0, +1.0, +1.0];

Segment:= [0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4, 0,4, 1,5, 2,6, 3,7]; SetVid($101); \set 640x480 graphics with 256 colors repeat Farthest:= 0.0; \find the farthest vertex

       for I:= 0 to 8-1 do
           if Z(I) > Farthest then [Farthest:= Z(I);  SI:= I];
       Clear;                          \erase screen
       for I:= 0 to 2*12-1 do          \for all the vertices...
           [J:= Segment(I);  I:= I+1;  \get vertex number
           Move(fix(X(J)*Size)+640/2, fix(Y(J)*Size)+480/2);
           K:= Segment(I);
           Line(fix(X(K)*Size)+640/2, fix(Y(K)*Size)+480/2,
               if J=SI ! K=SI then $F009 \dashed blue\ else $C \red\);
           ];
       Sound(0, 1, 1);                 \delay 1/18 second to prevent flicker
       for I:= 0 to 8-1 do
           [X(I):= X(I) + Y(I)*Sz;     \rotate vertices in X-Y plane
            Y(I):= Y(I) - X(I)*Sz;
            Y(I):= Y(I) + Z(I)*Sx;     \rotate vertices in Y-Z plane
            Z(I):= Z(I) - Y(I)*Sx;
           ];

until KeyHit; \run until a key is struck SetVid(3); \restore normal text mode (for DOS) ]</lang>

zkl

Draws a wire frame PPM image, no hidden/dotted lines.
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl <lang zkl>var [const] M=50.0; fcn cuboid(w,h,z){

  w*=M; h*=M; z*=M; // relative to abs dimensions
  bitmap:=PPM(400,400);
  clr:=0xff0000;  // red facing rectangle
  bitmap.line(0,0, w,0, clr); bitmap.line(0,0, 0,h, clr);
  bitmap.line(0,h, w,h, clr); bitmap.line(w,0, w,h, clr);
  r,a:=(w+z).toFloat().toPolar(0);  // relative to the origin
  a,b:=r.toRectangular((30.0).toRad() + a).apply("toInt"); c:=a; d:=b+h;
  clr=0xff; // blue right side of cuboid
  bitmap.line(w,0, a,b, clr); bitmap.line(a,b, c,d, clr);
  bitmap.line(w,h, c,d, clr);
  
  e:=c-w;
  clr=0xfff00; // green top of cuboid
  bitmap.line(0,h, e,d, clr); bitmap.line(c,d, e,d, clr);
  bitmap.write(File("foo.ppm","wb"));

}(2,3,4);</lang>

Output:

http://www.zenkinetic.com/Images/RosettaCode/cuboid.jpg

ZX Spectrum Basic

<lang zxbasic>10 LET width=50: LET height=width*1.5: LET depth=width*2 20 LET x=80: LET y=10 30 PLOT x,y 40 DRAW 0,height: DRAW width,0: DRAW 0,-height: DRAW -width,0: REM Front 50 PLOT x,y+height: DRAW depth/2,height: DRAW width,0: DRAW 0,-height: DRAW -width,-height 60 PLOT x+width,y+height: DRAW depth/2,height</lang>