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.

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.

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:

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

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>

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

Works with: MSWlogo

(MSWlogo can be downloaded here ([1]), available for all major versions of Windows.

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>

Mathematica

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.

Openscad

Drawing a cuboid is easy in openscad:

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

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

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

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

</lang> Example of output :

?- cuboid(2,3,4).
true.


[[

Python

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

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>