3d turtle graphics: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(7 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{draft task}}
Create a 3d representation of a house and bar chart, similar to that of [[Simple turtle graphics]], but
Create a 3d representation of a house and bar chart, similar to that of [[Simple turtle graphics]], but


* Use a cube and an equilateral square pyramid for the house, and
* (you can) use a cube for the house and an equilateral square pyramid for the roof, and
* use columns with a square cross section for the bar chart.
* (likewise if it helps) use columns with a square cross section for the bar chart.


=={{header|J}}==
=={{header|J}}==


Assumes jqt and a "recent" (2022) version of J.
Assumes jqt and a "recent" (2022) version of J.
<lang J>NB. pre-requisites:
<syntaxhighlight lang="j">NB. pre-requisites:
NB. ;install each cut 'gl2 gles github:zerowords/tgsjo'
NB. ;install each cut 'gl2 gles github:zerowords/tgsjo'
load'zerowords/tgsjo'
load'zerowords/tgsjo'
Line 24: Line 25:
forward height
forward height
pitch 90
pitch 90
}} y
}} y
forward width
forward width
right 90
right 90
}} y
}} y
}}
}}
Line 81: Line 82:
left 180
left 180
forward 30
forward 30
roll 180</lang>
roll 180</syntaxhighlight>

=={{header|Phix}}==
Fairly straightforward extension of Simple_turtle_graphics.exw, apart from the time spent staring at my own hand figuring out the sequences of angles.<br>
Reuses [[Simple_turtle_graphics#Phix|turtle.e]], however the code I really wanted to squirrel away has ended up in [[3d_turtle_graphics/Phix|turtle_projection.e]].
You can run this online [http://phix.x10.mx/p2js/3Dturtle.htm here].
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\3D_turtle_graphics.exw
-- ===================================
--
-- Fairly straightforward extension of Simple_turtle_graphics.exw, apart from
-- the time spent staring at my own hand figuring out the sequences of angles.
--
-- The turtle itself always draws in normal space, ie with the y axis vertical,
-- the x axis horizontal, and the z axis effectively a point, with any and all
-- 3D effects generated by projection onto a camera plane, which can be moved
-- about with the usual four arrow and +/- keys. Note the camera handling was
-- cribbed from demo/pGUI/rubik.e, less than perfect here but will have to do.
--
-- Invoking turn() (aka yaw) does pretty much what you would expect, whereas
-- roll() rotates about the direction of travel. To simulate pitch() (aka to
-- climb or nosedive) perform a roll(90), turn(pitch) sequence, avoiding any
-- temptation to "level off" before moving, as that just complicates angles.
--</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">turtle</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- (common code for 2D and 3D versions)</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">turtle_projection</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- (final 3D projection stuff)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">px</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">py</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pz</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- position</span>
<span style="color: #000000;">hx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hz</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- heading</span>
<span style="color: #000000;">nx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ny</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nz</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- normal</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">walk3D</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">//
// Move forward by distance d pixels.
//
// Aside: not entirely sure why rounding to 4dp (and normalising
// to 8dp) helps, but without it errors seem to build quickly..
// Of course in my opinion regularly teleporting the turtle back
// to {0,0,0} would just be cheating whereas this makes it exact
//</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">p1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">px</span><span style="color: #0000FF;">,</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">}</span>
<span style="color: #000000;">px</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">px</span><span style="color: #0000FF;">+</span><span style="color: #000000;">d</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">py</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">py</span><span style="color: #0000FF;">+</span><span style="color: #000000;">d</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">pz</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">+</span><span style="color: #000000;">d</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pen_down</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- (not entirely sure why it's "{y,x} =" either, but it is.)</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">y1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">y2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">}}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rotate_and_project</span><span style="color: #0000FF;">({</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">px</span><span style="color: #0000FF;">,</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">}})</span>
<span style="color: #7060A8;">cdCanvasLine</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">left_unit_vector</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hz</span><span style="color: #0000FF;">-</span><span style="color: #000000;">nz</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nz</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hy</span><span style="color: #0000FF;">-</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">*</span><span style="color: #000000;">hx</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">normalize</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_round</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)))),</span><span style="color: #000000;">100000000</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">v</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">ROLL</span><span style="color: #0000FF;">,</span><span style="color: #000000;">TURN</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">rot3D</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">angle</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">tp</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">angle</span> <span style="color: #0000FF;">*=</span> <span style="color: #004600;">CD_DEG2RAD</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">cos_a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">angle</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">sin_a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">angle</span><span style="color: #0000FF;">),</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">ux</span><span style="color: #0000FF;">,</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">uz</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">left_unit_vector</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">tp</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ROLL</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- aka rotation about the heading</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nz</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">normalize</span><span style="color: #0000FF;">({</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cos_a</span><span style="color: #0000FF;">-</span><span style="color: #000000;">ux</span><span style="color: #0000FF;">*</span><span style="color: #000000;">sin_a</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">ny</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cos_a</span><span style="color: #0000FF;">-</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">*</span><span style="color: #000000;">sin_a</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">nz</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cos_a</span><span style="color: #0000FF;">-</span><span style="color: #000000;">uz</span><span style="color: #0000FF;">*</span><span style="color: #000000;">sin_a</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">-- tp=TURN
-- aka rotation about the normal</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">hx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hz</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">normalize</span><span style="color: #0000FF;">({</span><span style="color: #000000;">hx</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cos_a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">ux</span><span style="color: #0000FF;">*</span><span style="color: #000000;">sin_a</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">hy</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cos_a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">*</span><span style="color: #000000;">sin_a</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">hz</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cos_a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">uz</span><span style="color: #0000FF;">*</span><span style="color: #000000;">sin_a</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- s is a list of {roll,turn,dist}, any of which can be 0.</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">roll</span><span style="color: #0000FF;">,</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dist</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">roll</span> <span style="color: #008080;">then</span> <span style="color: #000000;">rot3D</span><span style="color: #0000FF;">(</span><span style="color: #000000;">roll</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ROLL</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">turn</span> <span style="color: #008080;">then</span> <span style="color: #000000;">rot3D</span><span style="color: #0000FF;">(</span><span style="color: #000000;">turn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">TURN</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dist</span> <span style="color: #008080;">then</span> <span style="color: #000000;">walk3D</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dist</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">rectangle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">depth</span><span style="color: #0000FF;">=</span><span style="color: #000000;">width</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">depth</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">depth</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">depth</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">depth</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">depth</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">depth</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">draw_house</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">//
// Draw a house at the current position
// heading must be {1,0,0} for house to be upright
//
// house walls</span>
<span style="color: #000000;">pendown</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">rectangle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// door</span>
<span style="color: #000000;">penup</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">pendown</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_GREEN</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rectangle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">penup</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span>
<span style="color: #000080;font-style:italic;">// roof</span>
<span style="color: #000000;">walk3D</span><span style="color: #0000FF;">(</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">pendown</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_ORANGE</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{-</span><span style="color: #000000;">45</span><span style="color: #0000FF;">,</span><span style="color: #000000;">45</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">penup</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">45</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">135</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">45</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">pendown</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_ORANGE</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">135</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">}})</span>
<span style="color: #000080;font-style:italic;">// return to original position and direction</span>
<span style="color: #000000;">penup</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">45</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">135</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">height</span><span style="color: #0000FF;">}})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">draw_barchart</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">nums</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">// draw a barchart occupying the middle 60% of w,h
// nums can contain +ve and/or -ve values.</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nums</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">mx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nums</span><span style="color: #0000FF;">),</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">mn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nums</span><span style="color: #0000FF;">),</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">mn</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- range</span>
<span style="color: #000000;">zl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mn</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #000000;">h</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.6</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">/</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- zero line</span>
<span style="color: #000000;">bw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.6</span><span style="color: #0000FF;">/</span><span style="color: #000000;">n</span> <span style="color: #000080;font-style:italic;">-- bar width</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">w</span><span style="color: #0000FF;">/</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">zl</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">pendown</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">ni</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nums</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]/</span><span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #000000;">h</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.6</span>
<span style="color: #000000;">pendown</span><span style="color: #0000FF;">(</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ni</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #004600;">CD_ORANGE</span><span style="color: #0000FF;">:</span><span style="color: #004600;">CD_NAVY</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">rectangle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bw</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ni</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bw</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">penup</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">// return to origin({w/2,0}) and direction 0:</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span><span style="color: #000000;">zl</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">w</span><span style="color: #0000FF;">/</span><span style="color: #000000;">5</span><span style="color: #0000FF;">+</span><span style="color: #000000;">bw</span><span style="color: #0000FF;">*</span><span style="color: #000000;">n</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">hw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">qw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">qh</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">/</span><span style="color: #000000;">4</span>
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">cdCanvasClear</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">qh</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">qw</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">draw_house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">qw</span><span style="color: #0000FF;">,</span><span style="color: #000000;">qh</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- house in the left half</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">180</span><span style="color: #0000FF;">,</span><span style="color: #000000;">qh</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">qw</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span> <span style="color: #000080;font-style:italic;">-- return to {0,0}</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hw</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span> <span style="color: #000080;font-style:italic;">-- barchart in the right half</span>
<span style="color: #000000;">draw_barchart</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1.3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.5</span><span style="color: #0000FF;">},</span><span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rtm3D</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hw</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">90</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}})</span> <span style="color: #000080;font-style:italic;">-- return to {0,0}
-- sanity checks (but I got a 0.0002 under pwa/p2js when dev tools open...)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">({</span><span style="color: #000000;">px</span><span style="color: #0000FF;">,</span><span style="color: #000000;">py</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pz</span><span style="color: #0000FF;">}={</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">({</span><span style="color: #000000;">hx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hz</span><span style="color: #0000FF;">}={</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">({</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nz</span><span style="color: #0000FF;">}={</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">key_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #004600;">K_ESC</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CLOSE</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">axis</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,{</span><span style="color: #004600;">K_RIGHT</span><span style="color: #0000FF;">,</span><span style="color: #004600;">K_DOWN</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'+'</span><span style="color: #0000FF;">,</span><span style="color: #004600;">K_LEFT</span><span style="color: #0000FF;">,</span><span style="color: #004600;">K_UP</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">axis</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">angle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">axis</span><span style="color: #0000FF;">></span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">angle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">359</span>
<span style="color: #000000;">axis</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">3</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">view_rotations</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">view_rotations</span><span style="color: #0000FF;">[$][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">axis</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">view_rotations</span><span style="color: #0000FF;">[$][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">view_rotations</span><span style="color: #0000FF;">[$][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">angle</span><span style="color: #0000FF;">,</span><span style="color: #000000;">360</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">view_rotations</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">view_rotations</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">axis</span><span style="color: #0000FF;">,</span><span style="color: #000000;">angle</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">IupRedraw</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">view_rotations</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #7060A8;">IupRedraw</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_CONTINUE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupCanvas</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"RASTERSIZE=600x400"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`TITLE="3D turtle graphics"`</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupMap</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- release minimum limit</span>
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"KEY_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"key_cb"</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">IupSetAttributeHandle</span><span style="color: #0000FF;">(</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"PARENTDIALOG"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->

=={{header|Wren}}==
{{libheader|DOME}}
{{libheader|Wren-turtle}}
<syntaxhighlight lang="wren">import "dome" for Window
import "graphics" for Canvas, Color
import "math" for Math
import "./turtle" for Turtle

class Main {
construct new(width, height) {
Window.resize(width, height)
Canvas.resize(width, height)
Window.title = "3d turtle graphics"
_w = width
_h = height
}

init() {
Canvas.cls(Color.white)
_t = Turtle.new()
drawHouse3D(_w/4)
barChart([15, 10, 50, 35, 20], _w/3)
}

drawRectCuboid(x, y, hsize, vsize) {
// draw front rectangle
_t.drawRect(x, y, hsize, vsize)

// draw back rectangle
_t.drawRect(x + hsize/2, y - hsize/2, hsize, vsize)

var side = ((2 * hsize * hsize).sqrt/2).floor

// turn right 45 degrees
_t.right(45)
// goto bottom left front
_t.goto(x, y + vsize)
_t.walk(side)

// goto top left front
_t.goto(x, y)
_t.walk(side)

// goto bottom right front
_t.goto(x + hsize, y + vsize)
_t.walk(side)

// goto top right front
_t.goto(x + hsize, y)
_t.walk(side)
}

drawHouse3D(size) {
// save initial turtle position and direction
var saveX = _t.x
var saveY = _t.y
var saveD = _t.dir

_t.pen.width = 2

// draw house
drawRectCuboid(_w/8, _h/2, size, size)

// draw roof
_t.left(10)
_t.goto(_w/8, _h/2)
_t.walk(size)

_t.dir = 63
_t.walk((size*15/16).floor)
_t.back((size*15/16).floor)

_t.left(44)
_t.walk((size*31/32).floor)
_t.back((size*31/32).floor)
_t.dir = 102
_t.walk((size/3).floor)

// draw door
var doorWidth = (size/4).floor
var doorHeight = (size/2.5).floor
_t.drawRect(_w/4 + doorWidth/2, _h/2 + (size/2).floor - doorHeight, doorWidth, doorHeight)

// draw window
var windWidth = (size/3).floor
var windHeight = (size/4).floor
_t.drawRect(_w/4 + size/1.8, _h/2 + (size/2.8).floor - windHeight, windWidth, windHeight)

// restore initial turtle position and direction
_t.x = saveX
_t.y = saveY
_t.dir = saveD
}
// nums assumed to be all non-negative
barChart(nums, size) {
_t.pen.color = Color.brown

// save intial turtle position and direction
var saveX = _t.x
var saveY = _t.y
var saveD = _t.dir

// find maximum
var max = 0
for (n in nums) if (n > max) max = n

// scale to fit within a square with sides 'size' and draw chart
var barWidth = (size / nums.count).floor
var startX = _w / 2 + 20
var startY = _h / 2
for (i in 0...nums.count) { // nums.count) {
var barHeight = (nums[i] * size / max).round
drawRectCuboid(startX, startY - barHeight, barWidth, barHeight)
startX = startX + barWidth
}

// restore intial turtle position and direction
_t.x = saveX
_t.y = saveY
_t.dir = saveD
}

update() {}

draw(alpha) {}
}

var Game = Main.new(800, 800)</syntaxhighlight>

Latest revision as of 12:08, 5 November 2023

3d turtle graphics is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Create a 3d representation of a house and bar chart, similar to that of Simple turtle graphics, but

  • (you can) use a cube for the house and an equilateral square pyramid for the roof, and
  • (likewise if it helps) use columns with a square cross section for the bar chart.

J

Assumes jqt and a "recent" (2022) version of J.

NB. pre-requisites:
NB. ;install each cut 'gl2 gles github:zerowords/tgsjo'
load'zerowords/tgsjo'
stop''
clearscreen ''
createTurtle 0 0 0

EYE_tgsjo_=: 0 0 _90
rotR 180+94 10 0

column=: {{
    4 repeats {{'height width'=. y
        2 repeats {{'height width'=. y
            forward width
            pitch 90
            forward height
            pitch 90
        }} y
        forward width
        right 90
    }} y
}}

cube=: {{ column y,y }}

codihedral=: 180p_1*_3 o.%%:2
pyramid=: {{
    4 repeats {{
        roll codihedral
        pitch triangle y
        roll-codihedral
        forward y
        left 90
    }} y
}}      

NB. in 3d, we want to know which turning mechanism to use, when drawing a plane figure
triangle=: {{
    3 repeats (u {{
        forward y
        u 120
    }}) y
}}


house=: {{
    cube y
    roll 180
    pyramid y
}}

barchart=: {{'lst size'=. y
    if.#lst do.
        scale=. size%>./lst
        width=. size%#lst
        for_j. lst do.
            column (j * scale),width
            forward width
        end.
        back size
    end.
}}

penColor Red
house 150
pen 0
back 30
right 180
pen 1
penColor Blue
barchart 0.5 0.3333 2 1.3 0.5; 200
pen 0
left 180
forward 30
roll 180

Phix

Fairly straightforward extension of Simple_turtle_graphics.exw, apart from the time spent staring at my own hand figuring out the sequences of angles.
Reuses turtle.e, however the code I really wanted to squirrel away has ended up in turtle_projection.e. You can run this online here.

--
-- demo\rosetta\3D_turtle_graphics.exw
-- ===================================
--
--  Fairly straightforward extension of Simple_turtle_graphics.exw, apart from
--  the time spent staring at my own hand figuring out the sequences of angles.
--
--  The turtle itself always draws in normal space, ie with the y axis vertical,
--  the x axis horizontal, and the z axis effectively a point, with any and all
--  3D effects generated by projection onto a camera plane, which can be moved
--  about with the usual four arrow and +/- keys. Note the camera handling was 
--  cribbed from demo/pGUI/rubik.e, less than perfect here but will have to do.
--
--  Invoking turn() (aka yaw) does pretty much what you would expect, whereas 
--  roll() rotates about the direction of travel. To simulate pitch() (aka to 
--  climb or nosedive) perform a roll(90), turn(pitch) sequence, avoiding any
--  temptation to "level off" before moving, as that just complicates angles.
--
with javascript_semantics
include turtle.e -- (common code for 2D and 3D versions)
include turtle_projection.e -- (final 3D projection stuff)

atom px = 0, py = 0, pz = 0,    -- position
     hx = 1, hy = 0, hz = 0,    -- heading
     nx = 0, ny = 0, nz = 1     -- normal

procedure walk3D(atom d)
    //
    // Move forward by distance d pixels.
    //
    // Aside: not entirely sure why rounding to 4dp (and normalising
    //  to 8dp) helps, but without it errors seem to build quickly..
    //  Of course in my opinion regularly teleporting the turtle back 
    //  to {0,0,0} would just be cheating whereas this makes it exact
    //
    sequence p1 = {px,py,pz}
    px = round(px+d*hx,10000)
    py = round(py+d*hy,10000)
    pz = round(pz+d*hz,10000)
    if pen_down then
        -- (not entirely sure why it's "{y,x} =" either, but it is.)
        atom {{y1,x1},{y2,x2}} = rotate_and_project({p1,{px,py,pz}})
        cdCanvasLine(cdcanvas,x1,y1,x2,y2)
    end if
end procedure

function left_unit_vector()
    return {ny*hz-nz*hy,nz*hx-nx*hz,nx*hy-ny*hx}
end function

function normalize(sequence v)
    v = sq_round(sq_mul(v,1/sqrt(sum(sq_power(v,2)))),100000000)
    return v
end function

enum ROLL,TURN

procedure rot3D(atom angle, integer tp)
    angle *= CD_DEG2RAD
    atom cos_a = cos(angle),
         sin_a = sin(angle),
         {ux,uy,uz} = left_unit_vector()
    if tp=ROLL then
        -- aka rotation about the heading
        {nx,ny,nz} = normalize({nx*cos_a-ux*sin_a,
                                ny*cos_a-uy*sin_a,
                                nz*cos_a-uz*sin_a})
        
    else -- tp=TURN
        -- aka rotation about the normal
        {hx,hy,hz} = normalize({hx*cos_a+ux*sin_a,
                                hy*cos_a+uy*sin_a,
                                hz*cos_a+uz*sin_a})
    end if
end procedure

procedure rtm3D(sequence s)
    -- s is a list of {roll,turn,dist}, any of which can be 0.
    for i=1 to length(s) do
        atom {roll,turn,dist} = s[i]
        if roll then rot3D(roll,ROLL) end if
        if turn then rot3D(turn,TURN) end if
        if dist then walk3D(dist) end if
    end for
end procedure
    
procedure rectangle(atom width, height, depth=width)
    rtm3D({{ 0, 0,height},{  0,90,width},{0,90,height},{0,90,width},
           {90,-90,depth},{-90,90,height},{0,90,depth},{0,90,height},{0,90,depth},
           {90,-90,width},{-90,90,height},{0,90,width},{0,90,height},{0,90,width},
           {90,-90,depth},{-90,90,height},{0,90,depth},{0,90,height},{0,90,depth},
           {-90,90,width},{ 90,90,0}})
end procedure

procedure draw_house(atom width, height)
    //
    // Draw a house at the current position
    // heading must be {1,0,0} for house to be upright
    //
    // house walls
    pendown()
    rectangle(width, height)

    // door
    penup()
    rtm3D({{0,90,width/7},{0,-90,0}})
    pendown(CD_GREEN)
    rectangle(width/8,height/2.5,0)
    penup()
    rtm3D({{0,-90,width/7},{0,90,0}})

    // roof
    walk3D(height)
    pendown(CD_ORANGE)
    rtm3D({{-45,45,width},{0,90,width}})
    penup()
    rtm3D({{0,-45,0},{90,-135,width},{0,45,0}})
    pendown(CD_ORANGE)
    rtm3D({{90,135,width},{0,90,width}})

    // return to original position and direction
    penup()
    rtm3D({{0,-45,0},{90,135,width},{90,90,-height}})

end procedure

procedure draw_barchart(sequence nums, atom w, h)
    // draw a barchart occupying the middle 60% of w,h
    // nums can contain +ve and/or -ve values.
    integer n = length(nums)
    atom mx = max(max(nums),0),
         mn = min(min(nums),0),
         r = mx-mn,                 -- range
         zl = abs(mn)/r*h*0.6+h/5,  -- zero line
         bw = w*0.6/n               -- bar width
    rtm3D({{0,90,w/5},{0,-90,zl}})
    pendown()
    for i=1 to n do
        atom ni = nums[i]/r*h*0.6
        pendown(iff(ni<0?CD_ORANGE:CD_NAVY))
        rectangle(bw,ni)
        rtm3D({{0,90,bw},{0,-90,0}})
    end for
    penup()
    // return to origin({w/2,0}) and direction 0:
    rtm3D({{0,180,zl},{0,90,w/5+bw*n},{0,90,0}})
end procedure

function redraw_cb(Ihandle /*ih*/)
    integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE")
    atom hw = width/2, qw = width/4, qh = height/4
    cdCanvasActivate(cdcanvas)
    cdCanvasClear(cdcanvas)
    rtm3D({{0,0,qh},{0,90,qw},{0,-90,0}})

    draw_house(qw,qh)               -- house in the left half

    rtm3D({{0,180,qh},{0,90,qw},{0,90,0}}) -- return to {0,0}

    rtm3D({{0,90,hw},{0,-90,0}})    -- barchart in the right half

    draw_barchart({0.5, -4/3, 2, 1.3, 0.5},width/2,height)

    rtm3D({{0,-90,hw},{0,90,0}})    -- return to {0,0}

    -- sanity checks (but I got a 0.0002 under pwa/p2js when dev tools open...)
    if platform()!=JS then
        assert({px,py,pz}={0,0,0})
        assert({hx,hy,hz}={1,0,0})
        assert({nx,ny,nz}={0,0,1})
    end if

    cdCanvasFlush(cdcanvas)
    return IUP_DEFAULT
end function

function key_cb(Ihandle ih, atom c)
    if c=K_ESC then return IUP_CLOSE end if
    integer axis = find(c,{K_RIGHT,K_DOWN,'+',K_LEFT,K_UP,'-'})
    if axis then
        integer angle = 1
        if axis>3 then
            angle = 359
            axis -= 3
        end if
        if length(view_rotations) 
        and view_rotations[$][1] = axis then
            view_rotations[$][2] = mod(view_rotations[$][2]+angle,360)
        else
            view_rotations = append(view_rotations,{axis,angle})
        end if  
        IupRedraw(canvas)
    elsif c='0' then
        view_rotations = {}
        IupRedraw(canvas)
    end if      
    return IUP_CONTINUE
end function

IupOpen()
canvas = IupCanvas(Icallback("redraw_cb"),"RASTERSIZE=600x400")
dlg = IupDialog(canvas,`TITLE="3D turtle graphics"`)
IupMap(dlg)
cdcanvas = cdCreateCanvas(CD_IUP, canvas)
IupShow(dlg)
IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release minimum limit
IupSetCallback(dlg, "KEY_CB",  Icallback("key_cb"))
IupSetAttributeHandle(NULL, "PARENTDIALOG", dlg)
if platform()!=JS then
    IupMainLoop()
    IupClose()
end if

Wren

Library: DOME
Library: Wren-turtle
import "dome" for Window
import "graphics" for Canvas, Color
import "math" for Math
import "./turtle" for Turtle

class Main {
    construct new(width, height) {
        Window.resize(width, height)
        Canvas.resize(width, height)
        Window.title = "3d turtle graphics"
        _w = width
        _h = height
    }

    init() {
        Canvas.cls(Color.white)
        _t = Turtle.new()
        drawHouse3D(_w/4)
        barChart([15, 10, 50, 35, 20], _w/3)
    }

    drawRectCuboid(x, y, hsize, vsize) {
        // draw front rectangle
        _t.drawRect(x, y, hsize, vsize)

        // draw back rectangle
        _t.drawRect(x + hsize/2, y - hsize/2, hsize, vsize)

        var side = ((2 * hsize * hsize).sqrt/2).floor

        // turn right 45 degrees
        _t.right(45)
        
        // goto bottom left front
        _t.goto(x, y + vsize)
        _t.walk(side)

        // goto top left front
        _t.goto(x, y)
        _t.walk(side)

        // goto bottom right front
        _t.goto(x + hsize, y + vsize)
        _t.walk(side)

        // goto top right front
        _t.goto(x + hsize, y)
        _t.walk(side)
    }

    drawHouse3D(size) {
        // save initial turtle position and direction
        var saveX = _t.x
        var saveY = _t.y
        var saveD = _t.dir

        _t.pen.width = 2

        // draw house
        drawRectCuboid(_w/8, _h/2, size, size)

        // draw roof
        _t.left(10)
        _t.goto(_w/8, _h/2)
        _t.walk(size)

        _t.dir = 63
        _t.walk((size*15/16).floor)
        _t.back((size*15/16).floor)

        _t.left(44)
        _t.walk((size*31/32).floor)
        _t.back((size*31/32).floor)
        _t.dir = 102
        _t.walk((size/3).floor)

        // draw door
        var doorWidth  = (size/4).floor
        var doorHeight = (size/2.5).floor
        _t.drawRect(_w/4 + doorWidth/2, _h/2 + (size/2).floor - doorHeight, doorWidth, doorHeight) 

        // draw window
        var windWidth  = (size/3).floor
        var windHeight = (size/4).floor
        _t.drawRect(_w/4 + size/1.8, _h/2 + (size/2.8).floor - windHeight, windWidth, windHeight)

        // restore initial turtle position and direction
        _t.x = saveX
        _t.y = saveY
        _t.dir = saveD        
    }
      
    // nums assumed to be all non-negative
    barChart(nums, size) {
        _t.pen.color = Color.brown

        // save intial turtle position and direction
        var saveX = _t.x
        var saveY = _t.y
        var saveD = _t.dir

        // find maximum
        var max = 0
        for (n in nums) if (n > max) max = n

        // scale to fit within a square with sides 'size' and draw chart
        var barWidth = (size / nums.count).floor
        var startX = _w / 2 + 20
        var startY = _h / 2
        for (i in 0...nums.count) { // nums.count) {
            var barHeight = (nums[i] * size / max).round
            drawRectCuboid(startX, startY - barHeight, barWidth, barHeight)            
            startX = startX + barWidth
        }

        // restore intial turtle position and direction
        _t.x = saveX
        _t.y = saveY
        _t.dir = saveD
    }

    update() {}

    draw(alpha) {}
}

var Game = Main.new(800, 800)