Draw a cuboid

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

The task is to draw a cuboid with relative dimensions of 2x3x4.

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

To fulfil the criteria of being a cuboid, three faces must be visible.
Either static or rotational projection is acceptable for this task.

Contents

[edit] Ada

ASCII-Art output, one width unit is two characters long ('--').

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;
Output:
     +----+
    /    /|
   /    / |
  /    /  |
 /    /   +
+----+   / 
|    |  /  
|    | /   
|    |/    
+----+     

[edit] AutoHotkey

Library: GDIP
Some portions of code from Gdip examples.
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

[edit] 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

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

[edit] BBC BASIC

Uses BBC BASIC's native parallelogram plot.

      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
 
Output:

Cuboid BBC.gif

[edit] C

I think this code has bugs...

#include <stdio.h>
#include <stdlib.h>
#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;
}
Output:
                                *                                     

                       **************!!                              
               *************!!!!!!!!!!!!!!!!!!                       
        ooo************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!                
    *oooo***********!!!!!!!!!!!!!!!!!::::::::::::::::::::!!!         
    o*************!!!!!!!!!!!!:::::::::::::::::::::::::::::::::::::  
     o****!!****!!!!!!!!!!:::::::::::::::::::::::::::::::::::::::::&&
     oo****!!!!:!!!!!!!::::::::::::::::.................::::::::e&&& 
      o*****!!!!:::!!!:::::::::::............................eee&&&& 
      oo*****!!!!:::...:::::::.............................eeeee&&&  
       oo*****!!!!:::.....::............................oeeeeee&&&   
       ooo*****!!!!:::...............................ooooeeeee&&&&   
        ooo*****!!!!:::...........................ooooooeeeeee&&&    
        oooo*****!!!!::::......................**ooooooeeeeee&&&&    
          ooo*****!!!!::::..................****ooooooeeeeee&&&&     
            oo*****!!!!::::...............*****oooooooeeeeee&&&&     
              o*****!!!!::::..............****oooooooeeeeee&&&&      
                *****!!!!:::::............***oooooooeeeeee&&&        
                   ***!!!!!::::...........**oooooooeeeeee&&          
                     ***!!!!:::::.........ooooooooeeeeeee            
                       **!!!!!::::........oooooooeeeeee              
                         *!!!!!:::::.....oooooooeeeee                
                            !!!!!::::....oooooeeeee                  
                              !!!!:::::..ooooeeeee                   
                                !!!!:::::oooeeee                     
                                  !!!!:::oeeee                       
                                    !!!::eee                         
 !ee


[edit] C++

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

 
#include<graphics.h>
#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;
}
 
 

File:Box.jpg

[edit] Clojure

Library: quil
 
(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)
 
Output:

[1]

[edit] D

Translation of: Go
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);
}
Output:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

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

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

[edit] Elixir

Translation of: Ruby
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(0..x+y, fn i -> Dict.get(area, {i,j}, " ") end) |> Enum.join
end)
end
 
defp draw_line(area, n, sx, sy, c) do
{dx, dy} = Dict.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
area2 = Dict.update(area, {i,j}, c, fn _ -> :+ end)
draw_line(area2, 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)
Output:
cuboid 2 3 4:
      +-----+-----+
     /     /     /|
    +-----+-----+ |
   /     /     /| +
  +-----+-----+ |/|
 /     /     /| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/
|     |     |/| +
+-----+-----+ |/
|     |     | +
|     |     |/
+-----+-----+
cuboid 1 1 1:
  +-----+
 /     /|
+-----+ |
|     | +
|     |/
+-----+
cuboid 2 4 1:
        +-----+-----+
       /     /     /|
      +-----+-----+ |
     /     /     /| +
    +-----+-----+ |/
   /     /     /| +
  +-----+-----+ |/
 /     /     /| +
+-----+-----+ |/
|     |     | +
|     |     |/
+-----+-----+
cuboid 4 2 1:
    +-----+-----+-----+-----+
   /     /     /     /     /|
  +-----+-----+-----+-----+ |
 /     /     /     /     /| +
+-----+-----+-----+-----+ |/
|     |     |     |     | +
|     |     |     |     |/
+-----+-----+-----+-----+

[edit] Go

Translation of: PicoLisp
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)
}
Output:
cuboid 2 3 4:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

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

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

[edit] 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

CuboidHaskell.png

[edit] 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.

   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.........
*******...........
*******...........
*******...........
*******...........
*******...........
*******...........
*******...........
*******.........
*****.....
 
 

[edit] Java

Works with: Java version 8
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);
});
}
}

[edit] Liberty BASIC

Text solution

 
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
 
Output:
     +-------+
    /       /|
   /       / |
  /       /  |
 /       /   |
+-------+    |
|       |    |
|       |    |
|       |    |
|       |    |
|       |    +
|       |   /
|       |  /
|       | /
|       |/
+-------+

Graphic solution

 
NoMainWin
Global sw, sh
sw = 400: sh = 400
WindowWidth = sw+6
WindowHeight= sh+32
Open "[RC] Draw Cuboid" For graphics_nsb_nf As #g
#g "Down; Fill black; TrapClose [xit]"
#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
 

[edit]

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.

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

Example call to achieve task:

cuboid 50 100 150

[edit] LSL

Rez a box on the ground, raise it up a few meters, add the following as a New Script.

vector vSCALE = <2.0, 3.0, 4.0>;
default {
state_entry() {
llSetScale(vSCALE);
}
}
Output:
Ahhhhh; I always wondered what a Cuboid looked like, now I know!  :)

Draw a Cuboid
A Cuboid in a Sandbox.

[edit] Mathematica

This creates a cuboid with one corner at (0,0,0) and the opposite at (2,3,4):

Graphics3D[Cuboid[{0,0,0},{2,3,4}]]

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.

[edit] 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))$

[edit] Nim

Translation of: PicoLisp
import strutils
 
proc cline(n, x, y: int, cde: string) =
echo cde[0..0].align n+1,
repeatChar(9*x-1, cde[1]),
cde[0], cde[2..2].align y+1
 
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
Output:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

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

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

[edit] Openscad

Drawing a cuboid is easy in openscad:

// This will produce a simple cuboid
cube([2,3,4])

[edit] Pascal

Translation of: Ada
Works with: Free_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.
Output:
% ./Cuboid
1, 1, 1:
  +--------+
 /        /|
+--------+ |
|        | |
|        | +
|        |/ 
+--------+  
2, 3, 4:
     +----------------+
    /                /|
   /                / |
  /                /  |
 /                /   |
+----------------+    |
|                |    |
|                |    |
|                |    |
|                |    |
|                |    +
|                |   / 
|                |  /  
|                | /   
|                |/    
+----------------+     
6, 2, 1:
  +------------------------------------------------+
 /                                                /|
+------------------------------------------------+ |
|                                                | |
|                                                | |
|                                                | |
|                                                | |
|                                                | +
|                                                |/ 
+------------------------------------------------+ 

[edit] Perl

Translation of: Go
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;
Output:
cuboid 2 3 4:
    +-----------------+ 
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

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

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

ASCII Art

use 5.010;
 
# 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;

Cuboid(2,3,4)

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

[edit] Perl 6

Works with: niecza version 2012-07-26
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 Bool %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];
Output:

Cuboid Perl 6.png

[edit] Phix

Translated from XPL0. Included in the standard distribution as demo\rosetta\draw_cuboid.exw

CuboidXPL0.gif
include ..\arwen\arwen.ew
include ..\arwen\axtra.ew
 
constant main = create(Window, "Draw Cuboid", 0, 0, 20, 20, 625, 690, 0),
mainDC = getPrivateDC(main),
backDC = c_func(xCreateCompatibleDC, {NULL}), -- the background
viewDC = c_func(xCreateCompatibleDC, {NULL}), -- with animation
grey = #909090
 
constant MainTimer = createTimer()
 
integer dw = 0, dh = 0 -- client area width and height
atom bmBack, bmView
integer bmX = 0, bmY = 0 -- actual size of the bitmaps
 
-- 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},
Segment = {1,2, 2,3, 3,4, 4,1, 5,6, 6,7, 7,8, 8,5, 1,5, 2,6, 3,7, 4,8}
 
constant Size=50.0, Sz=0.008, Sx=-0.013 -- drawing size and tumbling speeds
 
function mainHandler(integer id, integer msg, atom wParam, object lParam)
atom farthest
integer v1, v2, farv, c
if msg=WM_SIZE then
{{},{},dw,dh} = getClientRect(main)
if dw>bmX or dh>bmY then
-- we need bigger bitmaps
bmBack = c_func(xCreateCompatibleBitmap, {mainDC, dw, dh})
{} = deleteObject(selectObject(backDC,bmBack))
-- clear the background
setPenColor(grey)
setPenBkColor(grey)
drawRectangleh(backDC, True, 0, 0, dw, dh)
bmView = c_func(xCreateCompatibleBitmap, {mainDC, dw, dh})
{} = deleteObject(selectObject(viewDC,bmView))
{bmX,bmY} = {dw,dh}
end if
elsif msg=WM_PAINT then
-- start with a fresh copy of the background
void = c_func(xBitBlt,{viewDC,0,0,dw,dh,backDC,0,0,SRCCOPY})
farthest = 0.0 -- find the farthest vertex
for i=1 to 8 do
if z[i]>farthest then farthest = z[i] farv = i end if
end for
for v=1 to 2*12 by 2 do -- for all the vertices...
v1 = Segment[v] -- get vertex number
v2 = Segment[v+1]
c = Red; setPenStyle(Solid)
if v1=farv or v2=farv then c=Blue; setPenStyle(Dash) end if
drawLinesh(viewDC,{c,{x[v1]*Size+dw/2, y[v1]*Size+dh/2,
x[v2]*Size+dw/2, y[v2]*Size+dh/2}})
end for
void = c_func(xBitBlt,{mainDC,0,0,dw,dh,viewDC,0,0,SRCCOPY})
elsif msg=WM_TIMER then
for i=1 to 8 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
end for
repaintWindow(main)
elsif msg=WM_SHOWWINDOW then
startTimer(MainTimer,main,33)
elsif msg=WM_CHAR
and wParam=VK_ESCAPE then
closeWindow(main)
if id or object(lParam) then end if -- suppress warnings
end if
return 0
end function
setHandler({main},routine_id("mainHandler"))
 
WinMain(main, SW_NORMAL)

[edit] PicoLisp

[edit] Using ASCII

(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) )
Output:
: (cuboid 2 3 4)
    +-----------------+
   /                 /|
  /                 / |
 /                 /  |
+-----------------+   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   |
|                 |   +
|                 |  /
|                 | /
|                 |/
+-----------------+

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

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

[edit] Using OpenGL

Library: GLUT
(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)

[edit] 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>
}

PovRay-cuboid.jpg

[edit] Prolog

Works with SWI-Prolog and XPCE.

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, Hight, Color) :->
send(P, send_super, initialise),
send(P, append, Pos),
H is ceiling(sqrt(Hight * 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, Hight, 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 + Hight,
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.
Output:
?- cuboid(2,3,4).
true.

Prolog-Cuboid.png

[edit] Pure Data

Requires `Gem`

 
#N canvas 1 51 450 300 10;
#X obj 66 67 gemwin;
#X obj 239 148 cuboid 2 3 4;
#X obj 239 46 gemhead;
#X obj 239 68 scale 0.3;
#X msg 66 45 lighting 1 \, create \, 1;
#X obj 61 118 gemhead;
#X obj 61 140 world_light;
#X msg 294 90 1;
#X obj 239 90 t a b;
#X obj 239 118 accumrotate;
#X connect 2 0 3 0;
#X connect 3 0 8 0;
#X connect 4 0 0 0;
#X connect 5 0 6 0;
#X connect 7 0 9 1;
#X connect 7 0 9 2;
#X connect 7 0 9 3;
#X connect 8 0 9 0;
#X connect 8 1 7 0;
#X connect 9 0 1 0;
 

Displays a rotating cuboid.


File:PureData-cuboid.png

[edit] Python

[edit] Ascii-Art

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')
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+

[edit]
Library: VPython

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

Works with: Python version 2.7.5

[edit] Short version

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"

[edit] 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.

 
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....+....2....+....3....+....4....+....5....+....6....+....7....+...
 
## 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) )
 
## 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
 
## 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)
#c = col.next()
#c = next(col)
def paint(obj) :
c = next(col)
print("Color=",c)
obj.color = c
 
## 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
 
## 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
 
## 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)
 
## List of keypresses for demo:
 
#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....+....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....+....2....+....3....+....4....+....5....+....6....+....7....+...
 
scene.width = 600
scene.height = 400
scene.range = 4
#scene.autocenter = True
#scene.background = color.gray(0.2)
scene.background = next(bg)
 
autoDemo = -1
 
print( msg )
 
 
## Create cuboid (aka "box") :
 
# c = box() # using default-values --> cube
# c = box(pos=(0,0,0), length=4, height=2, width=3, axis=(-0.1,-0.1,0.1) )
##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 ),
## color = color.orange,
## opacity = 1.0,
## material= materials.marble
## )
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)
 
#sceneInfo(scene)
#objInfo(c)
print("\nPress 'a' to start auto-running demo.")
 
#...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+...
 
 
## 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()
 

[edit] PureBasic

Using generic PureBasic 2D-library.

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
 
#WFlags = #PB_Window_SystemMenu|#PB_Window_SizeGadget
#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

PB Cuboid.png

[edit] 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)

Racket cuboid.png

[edit] 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
Output:
     +----+
    /    /|
   /    / |
  /    /  |
 /    /   +
+----+   / 
|    |  /  
|    | /   
|    |/    
+----+     

[edit] REXX

/*REXX program to draw a cuboid  (dimensions must be positive integers).*/
parse arg x y z indent . /*x,y,z: dimensions, indentation.*/
x=p(x 2); y=p(y 3); z=p(z 4) /*use defaults if not specified. */
in=p(indent 0)
call show y+2 , , "+-"
do j=1 for y; call show y-j+2, j-1, "/ |"  ; end
call show , y , "+-|"
do z-1; call show , y , "| |"  ; end
call show , y , "| +"
do j=1 for y; call show , y-j, "| /"  ; end
call show , , "+-"
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────P subroutine────────────────────────*/
p: return word(arg(1), 1) /*pick the 1st "word" in the list*/
/*──────────────────────────────────SHOW subroutine─────────────────────*/
show: parse arg #,$,a 2 b 3 c 4 /*get the args (or parts thereof)*/
say left('',in)right(a,p(# 1))copies(b,4*x)a || right(c,p($ 0)+1); return
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
                            +------------------------+
                           /                        /|
                          /                        / |
                         +------------------------+  |
                         |                        |  +
                         |                        | /
                         |                        |/
                         +------------------------+

[edit] 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)
Output:
cuboid 2 3 4:
      +-----+-----+
     /     /     /|
    +-----+-----+ |
   /     /     /| +
  +-----+-----+ |/|
 /     /     /| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/|
|     |     |/| + |
+-----+-----+ |/| +
|     |     | + |/ 
|     |     |/| +  
+-----+-----+ |/   
|     |     | +    
|     |     |/     
+-----+-----+      
cuboid 1 1 1:
  +-----+
 /     /|
+-----+ |
|     | +
|     |/ 
+-----+  
cuboid 6 2 1:
    +-----+-----+-----+-----+-----+-----+
   /     /     /     /     /     /     /|
  +-----+-----+-----+-----+-----+-----+ |
 /     /     /     /     /     /     /| +
+-----+-----+-----+-----+-----+-----+ |/ 
|     |     |     |     |     |     | +  
|     |     |     |     |     |     |/   
+-----+-----+-----+-----+-----+-----+    
cuboid 2 4 1:
        +-----+-----+
       /     /     /|
      +-----+-----+ |
     /     /     /| +
    +-----+-----+ |/ 
   /     /     /| +  
  +-----+-----+ |/   
 /     /     /| +    
+-----+-----+ |/     
|     |     | +      
|     |     |/       
+-----+-----+        

[edit] Sidef

Translation of: Ruby
var DIR = Hash.new("-" => [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) {
DIR[c]»(\var dx, \var dy);
0..n -> each {|i|
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.call(x, 0, 4*i, "-")};
0 .. ny -> each {|i| line.call(x, 2*i, z + 2*i, "-")};
0 .. nx-1 -> each {|i| line.call(z, 8*i, 0, "|")};
0 .. ny -> each {|i| line.call(z, x + 2*i, 2*i, "|")};
0 .. nz-1 -> each {|i| line.call(y, x, 4*i, "/")};
0 .. nx -> each {|i| line.call(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);

A faster approach:

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
} * 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;
} * y;
 
c + h*x + c -> say;
};
 
cuboid(x:2, y:3, z:4);
cuboid(x:1, y:1, z:1);
cuboid(x:6, y:2, z:1);
cuboid(x:2, y:4, z:1);
Output:
cuboid 2 3 4:
     +--+
    /  /|
   /  / |
  /  /  |
 /  /   +
+--+   /
|  |  /
|  | /
|  |/
+--+
cuboid 1 1 1:
  +-+
 / /|
+-+ +
| |/
+-+
cuboid 6 2 1:
  +------+
 /      /|
+------+ |
|      | +
|      |/
+------+
cuboid 2 4 1:
  +--+
 /  /|
+--+ |
|  | |
|  | |
|  | +
|  |/
+--+


[edit] Tcl

Library: Tk
Library: Tcllib (Package: math::linearalgebra)
Library: Tcllib (Package: math::constants)
package require Tcl 8.5
package require Tk
package require math::linearalgebra
package require math::constants
 
# 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
}
 
# 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"]
}
 
# Project a shape onto a surface (Tk canvas); assumes that the shape's faces
# 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
}
}
 
# How to construct the projection transform.
# 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]
}
}
### End of definitions
 
# 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

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):

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
}

[edit] XPL0

CuboidXPL0.gif
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)
]

[edit] 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

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);
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox