Hypertext Markup "index"

Admin User, created Apr 23. 2025
         
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title editable="nocomment">Example 12</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<!-- Warranty & Liability -->
<!-- To the extent permitted by applicable law and unless explicitly -->
<!-- otherwise agreed upon, XLOG Technologies AG makes no warranties -->
<!-- regarding the provided information. XLOG Technologies AG assumes -->
<!-- no liability that any problems might be solved with the information -->
<!-- provided by XLOG Technologies AG. -->
<!-- -->
<!-- Rights & License -->
<!-- All industrial property rights regarding the information - copyright -->
<!-- and patent rights in particular - are the sole property of XLOG -->
<!-- Technologies AG. If the company was not the originator of some -->
<!-- excerpts, XLOG Technologies AG has at least obtained the right to -->
<!-- reproduce, change and translate the information. -->
<!-- -->
<!-- Reproduction is restricted to the whole unaltered document. -->
<!-- Reproduction of the information is only allowed for non-commercial -->
<!-- uses. Selling, giving away or letting of the execution of the -->
<!-- library is prohibited. The library can be distributed as part of -->
<!-- your applications and libraries for execution provided this comment -->
<!-- remains unchanged. -->
<!-- -->
<!-- Restrictions -->
<!-- Only to be distributed with programs that add significant and primary -->
<!-- functionality to the library. Not to be distributed with additional -->
<!-- software intended to replace any components of the library. -->
<!-- -->
<!-- Trademarks -->
<!-- Jekejeke is a registered trademark of XLOG Technologies AG. -->
<body>
<h1>Example 12: Turtle Graphics</h1>
<h2>Introduction</h2>
<p>In this example we cover various aspects of the Dogelog Player
integration with the browser, such as library(markup) and library(vector).
At the same time the example delivers an exercise in dynamic database
and recursion.</p>
<h2>library(markup)</h2>
<p>A Prolog system maintains a state through their input, output and
error streams. In the case of a browser environment the corresponding
output and error streams point to DOM elements, which
can be simultaneously set via set_cursor().</p>
<pre class="code">
:- current_output(S), write(S, 'Hello World!'), nl(S).
</pre>
<p>The error stream will also do some text coloring:</p>
<pre class="code">
:- current_error(S), write(S, 'Hello World!'), nl(S).
</pre>
<p>There are also factory predicates in library(markup) to create more
such markup streams. Markup streams act on their cursor elem as
defined in library(markup):</p>
<pre>
Prolog Action
write('foo &lt; bar') elem.insertAdjacentText("beforeend", "foo &lt; bar")
tag('&amp;amp;') elem.insertAdjacentHTML("beforeend", "&amp;amp;")
tag('&lt;foo&gt;') elem.insertAdjacentHTML("beforeend", "&lt;foo&gt;&lt;/foo&gt;");
elem = elem.lastElementChild
tag('&lt;/foo&gt;') elem = elem.parentElement
tag('&lt;foo/&gt;') elem.insertAdjacentHTML("beforeend", "&lt;/foo&gt;")
</pre>
<p>This allows for complex dynamic HTML output:</p>
<pre class="code">
:- ensure_loaded(library(misc/markup)).
bullets(L, H) :-
tag('&lt;ol>'),
(between(L, H, I),
tag('&lt;li>'),
write('List item '), write(I),
tag('&lt;/li>'),
fail; true),
tag('&lt;/ol>').
:- bullets(1, 3).
</pre>
<h2>library(vector)</h2>
<p>This file provides convenience predicates to generate the markup for
scalable vector graphics (SVG). The predicates require a markup writer
as found in library(markup), either explicit as a parameter or implicit
as current output. We can define a turtle drawing area:</p>
<pre class="code">
:- ensure_loaded(library(misc/vector)).
begin :-
retractall(current_angle(_)),
assertz(current_angle(0)),
retractall(current_position(_,_)),
assertz(current_position(50,350)),
svg_begin([style('stroke: peru; fill: peachpuff')]).
end :-
svg_end.
test :-
begin,
end.
:- test.
</pre>
<p>The SVG output area will have 500x400 SVG coordinate dimension and a
twelfth of it in relative font size as browser dimension. We can draw a
little arrow to indicate the location and orientation of the turtle:</p>
<pre class="code">
show :-
current_position(X, Y),
current_angle(A),
svg_group_begin(X, Y, A),
svg_path(['M', 5, 0, 'L', -2.5, -5,
'Q', -5, 0, -2.5, 5, 'Z'], []),
svg_group_end.
test2 :-
begin,
show,
end.
:- test2.
</pre>
<h2>Turtle</h2>
<p>We can realize turtle commands by modifying the dynamic database. There is
a command turn/1, which affects the orientation of the turtle, and there is a
command move/1 which affects the location of the turtle, by traveling a
distance along the current orientation:</p>
<pre class="code">
turn(D) :-
retract(current_angle(A)), !,
A2 is A+D,
assertz(current_angle(A2)).
move(D) :-
retract(current_position(X1,Y1)), !,
current_angle(A),
X2 is X1+D*cos(A),
Y2 is Y1+D*sin(A),
assertz(current_position(X2,Y2)).
test3 :-
begin,
move(200),
turn(-pi/2),
move(100),
show,
end.
:- test3.
</pre>
<p>Besides modifying the dynamic database we can also affect the
browser DOM. Here the line/1 command works like the move/1 command,
except that the turtle will leave a trace in the drawing area:</p>
<pre class="code">
line(D) :-
retract(current_position(X1,Y1)), !,
current_angle(A),
X2 is X1+D*cos(A),
Y2 is Y1+D*sin(A),
assertz(current_position(X2,Y2)),
svg_line(X1, Y1, X2, Y2, []).
test4 :-
begin,
line(200),
turn(-pi/2),
line(100),
show,
end.
:- test4.
</pre>
<h2>Sierpinski</h2>
<p>A popular visualization of recursion are fractal curves. The basic element
of the Sierpinski courve is a triangle. It can be arranged that the turtel
returns to its original location and orientation:</p>
<pre class="code">
sierpinski(0, D) :- !, line(D), turn(-pi*2/3), line(D),
turn(-pi*2/3), line(D), turn(pi*4/3).
test5 :-
begin,
sierpinski(0, 400),
show,
end.
:- test5.
</pre>
<p>We can repeat the process recursively, putting a triangle into the
top of the triangle, the left bottom of the triangle and the right bottom
of the triangle. Amazingly it was again arrange that the turtle returns
to its original location and orientation:</p>
<pre class="code">
:- discontiguous sierpinski/2.
sierpinski(L, D) :- D2 is D/2, L2 is L-1,
sierpinski(L2, D2), move(D2), sierpinski(L2, D2),
turn(-pi*2/3), move(D2), turn(pi*2/3), sierpinski(L2, D2),
turn(pi*2/3), move(D2), turn(-pi*2/3).
test6 :-
begin,
sierpinski(1, 400),
show,
end.
:- test6.
</pre>
<p>If we repeat the process more than once, we start seeing the Sierpinski
fractal. Since markup streams immediately update the DOM model and the
underlying Prolog system automatically yields, the browser will reflect
the SVG changes and we can watch how the fractal is drawn:</p>
<pre class="code">
test7 :-
begin,
sierpinski(7, 400),
end.
:- test7.
</pre>
<h2>Conclusions</h2>
<script type="module">
import {
notebook_async
} from "../../../../dogelog/player/canned/dogelog.mjs";
await notebook_async();
</script>
</body>
</html>