<?xml version="1.0" encoding="utf-8"?>
<document xmlns="http://cnx.rice.edu/cnxml" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:md="http://cnx.rice.edu/mdml/0.4" xmlns:bib="http://bibtexml.sf.net/" xmlns:q="http://cnx.rice.edu/qml/1.0" id="None" module-id="" cnxml-version="0.6">
  <title>Graphic Composition in Processing</title>
  <metadata xmlns:md="http://cnx.rice.edu/mdml/0.4">
  <!-- WARNING! The 'metadata' section is read only. Do not edit below.
       Changes to the metadata section in the source will not be saved. -->
  <md:content-id>m12986</md:content-id>
  <md:title>Graphic Composition in Processing</md:title>
  <md:version>1.9</md:version>
  <md:created>2005/08/14 07:19:40 GMT-5</md:created>
  <md:revised>2009/05/20 06:47:27.271 GMT-5</md:revised>
  <md:authorlist>
    <md:author id="drocchesso">
        <md:firstname>Davide</md:firstname>
        <md:surname>Rocchesso</md:surname>
        <md:fullname>Davide Rocchesso</md:fullname>
        <md:email>roc@iuav.it</md:email>
    </md:author>
  </md:authorlist>
  <md:maintainerlist>
    <md:maintainer id="drocchesso">
        <md:firstname>Davide</md:firstname>
        <md:surname>Rocchesso</md:surname>
        <md:fullname>Davide Rocchesso</md:fullname>
        <md:email>roc@iuav.it</md:email>
    </md:maintainer>
  </md:maintainerlist>
  <md:license href="http://creativecommons.org/licenses/by/2.0/"/>
  <md:licensorlist>
    <md:licensor id="drocchesso">
        <md:firstname>Davide</md:firstname>
        <md:surname>Rocchesso</md:surname>
        <md:fullname>Davide Rocchesso</md:fullname>
        <md:email>roc@iuav.it</md:email>
    </md:licensor>
  </md:licensorlist>
  <md:parent-module href="http://cnx.org/content/m12665/1.7/">
    <md:content-id>m12665</md:content-id>
    <md:title>Graphic Composition in Processing</md:title>
    <md:authorlist>
      <md:author id="drocchesso">
        <md:firstname>Davide</md:firstname>
        <md:surname>Rocchesso</md:surname>
        <md:fullname>Davide Rocchesso</md:fullname>
        <md:email>roc@iuav.it</md:email>
      </md:author>
    </md:authorlist>
    <md:license href="http://creativecommons.org/licenses/by/2.0/"/>
    <md:licensorlist>
      <md:licensor id="drocchesso">
        <md:firstname>Davide</md:firstname>
        <md:surname>Rocchesso</md:surname>
        <md:fullname>Davide Rocchesso</md:fullname>
        <md:email>roc@iuav.it</md:email>
      </md:licensor>
    </md:licensorlist>
  </md:parent-module>
  <md:keywordlist>
    <md:keyword>2D graphics</md:keyword>
    <md:keyword>3D graphics</md:keyword>
    <md:keyword>curves</md:keyword>
  </md:keywordlist>
  <md:subjectlist>
    <md:subject>Science and Technology</md:subject>
  </md:subjectlist>
  <md:abstract>Elements of 2D and 3D graphic composition (including curves) for the Processing language and environment.</md:abstract>
  <md:language>en</md:language>
  <!-- WARNING! The 'metadata' section is read only. Do not edit above.
       Changes to the metadata section in the source will not be saved. -->
</metadata>

  <content>
    <section id="primitive_grafiche">
      <title>Graphic primitives</title>
      <para id="primp">
      In Processing, we can arrange points, lines, surfaces, and
      volumes (objects in 0, 1, 2, and 3 dimensions, respectively) in
      a 3D space or, where this makes sense in the 2D space of the
      image window. The number of parameters of the object primitives
      will determine if these objects have to be positioned in the X-Y or
      in the X-Y-Z space.
      </para>
      <section id="zeroD">
	<title>0D</title> <para id="punti"><title>Points</title> The
	<code>point()</code> is the simplest of the graphic
	primitives. When invoked with two coordinate parameters, it
	positions a point in the X-Y space. When invoked with three
	coordinate parameters, it positions a point in the X-Y-Z
	space. A point, in geometric sense, does not have dimension,
	but it can be assigned an occupation in pixels and a color, by
	the functions <code>strokeWeight()</code> and
	<code>stroke()</code>, respectively. For example, the simple
	Processing sketch
	<code id="id1165052307431" display="block">
	  stroke(180,0,0);
	  strokeWeight(10);
	  point(60,60);
	</code>
	draws a  dot in the image window.
	</para>
	<para id="collezioni_punti"><title>Collections of points</title>
	  A set of points can be grouped into a single object (cloud
	  of points) by the delimiters <code>beginShape(POINTS)</code>
	  and <code>endShape()</code>. Between them each point has to
	  be specified with the <code>vertex()</code>
	  function. Transformations of rotation, translation, and
	  scaling do not apply to the inside of composite objects
	  described with <code>beginShape()</code> and
	  <code>endShape()</code>, but they can precede the definition
	  of a composite object and apply to the whole.
	</para>
      </section>
      <section id="unoD">
	<title>1D</title> <para id="rette"><title>Straight Lines</title>
	The <code>line()</code> draws a line segment between two
	points in the plane or the 3D space, with width and color that
	can be set with <code>strokeWeight()</code> and
	<code>stroke()</code>, respectively.
	</para>
	<para id="collezioni_segmenti"><title>Collections of
	segments</title> A set of segments can be defined, as we saw
	for points, by the delimiters <code>beginShape()</code> and
	<code>endShape()</code>. Between them, vertices are listed by
	calls to the function <code>vertex()</code>. Using the
	invocation <code>beginShape(LINES)</code> the vertices are
	taken in couples, each identifying a segment. With the argument-free
	invocation <code>beginShape()</code> the vertices,
	taken one after the other, define a polygonal line. With the
	closure <code>endShape(CLOSE)</code> the line is
	closed on itself by linking the first and last
	vertices. The color of such polygon can be set by using the <code>fill()</code> function or, conversely, left equal to the background color with the <code>noFill()</code>.
	</para>
	<para id="curve"><title>Curves</title>The function
	<code>curve()</code>, when called with eight parameters, draws
	a curve on the image plane, with initial and final points
	determined, respectively, by the second and third couple of
	coordinates passed as arguments. The first and last couple of
	coordinates define two control points for the curve, which is
	an interpolating spline, thus passing for all four points. In Processing, however, only the curve segment between the intermediate points is visualized.
	<definition id="spline">
	  <term>Spline</term> <meaning id="id1165052324059">Piecewise-polynomial curve,
	  with polynomials connected with continuity at the
	  <emphasis>knots</emphasis><note id="id1165052324067">See <link document="m11153">Introduction to Splines</link> and, for an
	  introduction to the specific kind of splines (Catmull-Rom)
	  used in Processing, the term <term url="http://en.wikipedia.org/wiki/Spline_%28mathematics%29">
	  spline </term> in Wikipedia.</note></meaning>
	</definition>
	In order to have an arbitrary number of control points we must
	use the function <code>curveVertex()</code> to specify each
	point in the block delimited by
	<code>beginShape()</code> and
	<code>endShape()</code>.
	</para>
	<para id="bezier">As opposed to the <code>curve()</code>, in
	the <code>bezier()</code> function call the two control points
	specified by the four middle parameters are not points touched
	by the curve. They only serve to define the shape of the <term url="http://en.wikipedia.org/wiki/B%e9zier_curve">approximating
	Bézier curve</term>, which has the following interesting
	properties:
	  <list id="proprieta_bezier">
	    <item>it is entirely contained in the <term>convex
	    hull</term> defined by the extremal points and the control
	    points;</item> <item>transformations of translation,
	    rotation, or scaling, appied to the extremal and control
	    points determine a similar transformation of the
	    curve.</item>
	  </list>
	As we can see by running the code
	<code id="id1165052324156" display="block">stroke(255, 0, 0); 
line(93, 40, 10, 10); 
line(90, 90, 15, 80); 
stroke(0, 0, 0); 
noFill();
bezier(93, 40, 10, 10, 90, 90, 15, 80);
	</code>
	  the control points lay on the tangent passing by the
	  extremal points. In order to have an arbitrary number of
	  control points one must use the <code>bezierVertex()</code>
	  to specify each point within a block delimited by
	  <code>beginShape()</code> and
	  <code>endShape()</code>. In this way, an arbitrarily
	  involute curve can be traced in the 3D space. In 2D, the
	  function <code>bezierVertex()</code> has six parameters that
	  correspond to the coordinates of two control points and one
	  anchor point. The first invocation of
	  <code>bezierVertex()</code> has to be preceded by a call to
	  <code>vertex()</code> which fixes the first anchor point of
	  the curve.
	</para>
	<para id="extracurvep">
	  There are other methods that allow to read the coordinates
	  or the slope of the tangent to an arbitrary point of a
	  Bézier or spline curve. Such point can be specified by a
	  parameter <m:math> <m:ci>t</m:ci> </m:math> that can go from
	  <m:math> <m:mn>0</m:mn> </m:math> (first extreme) to
	  <m:math> <m:mn>1</m:mn> </m:math> (second extreme). It is
	  also possible to set the precision of approximating or
	  interpolating curves in 3D. For details see the <link url="http://www.processing.org/reference/index_ext.html">Processing
	  reference manual </link>.
	</para>
	<para id="beziercurve">The Processing sketch in <link target-id="bezier_curve_table"> table </link> shows the difference between the spline interpolating curve and the 
	  Bézier curve.<note id="id1165052305580">See the term <term url="http://en.wikipedia.org/wiki/B%e9zier_curve">Bézier
	  curve</term> in Wikipedia.</note>
	    <table id="bezier_curve_table" frame="all" summary="">
<tgroup cols="2" align="left" colsep="1" rowsep="1"><colspec colname="col1" colnum="1" colwidth="50"/>
		<colspec colname="col2" colnum="2" colwidth="300"/>
		<tbody>
		  <row>
		    <entry>
		      <link resource="bezier_curve.html">applet that
		      compares the Bézier curve (red) and the
		      interpolating spline (black) </link>
		    </entry>
		    <entry>
	    <code id="id1165052305663" display="block">
            
                
void setup() {
  c1x = 120;
  c1y = 110;
  c2x = 50;
  c2y = 70;
  background(200);
  stroke(0,0,0);
  size(200, 200);
}

int D1, D2;
int X, Y;
int c1x, c1y, c2x, c2y;

void draw() {
  if (mousePressed == true) {
    X = mouseX; Y = mouseY;
    // selection of the point that is modified
    D1 = (X - c1x)*(X - c1x) + (Y - c1y)*(Y - c1y); 
    D2 = (X - c2x)*(X - c2x) + (Y - c2y)*(Y - c2y);
    if (D1 &lt; D2) {
    c1x = X; c1y = Y;
    }
    else {
     c2x = X; c2y = Y;
     }
    }
    background(200);
    stroke(0,0,0);
    strokeWeight(1);
    
    noFill();
    beginShape(); 
    curveVertex(10,  10); 
    curveVertex(10,  10); 
    curveVertex(c2x, c2y); 
    curveVertex(c1x, c1y); 
    curveVertex(190, 190); 
    curveVertex(190, 190); 
    endShape(); 
       
    stroke(255,30,0);
    bezier(10,10,c2x,c2y,c1x,c1y,190,190);
    strokeWeight(4);
    point(c1x,c1y);
    point(c2x,c2y);
}
                   	      
	    </code>
		    </entry>
		  </row>
		</tbody>
	      


</tgroup>
</table>
  	</para>
     </section>
      <section id="dueD">
	<title>2D</title> <note id="id1165052305701">Objects in two or three dimensions take
	a color that can be determined by the illumination, as
	explained in <link target-id="illuminazione"/>, or established by
	the method <code>fill()</code>, which also gives the
	possibility to set the degree of transparency.</note>

	<para id="triangoli"><title>Triangles</title> The triangle is
	the fundamental construction element for 3D graphics. In fact,
	by juxtaposition of triangles one can approximate any
	continuous surface. In Processing, however, the triangles
	are specified in 2D by the primitive <code>triangle()</code>,
	whose six parameters correspond to the coordinates of the
	vertices in the image window. Even though each triangle is
	defined in 2D, it can be rotated and translated in the 3D
	space, as it happens in the Processing sketch
	<code id="id1165052305746" display="block"> void setup(){ size(200, 200, P3D); fill(210, 20,
	20); }

	float angle = 0;

	void draw(){
	    background(200); // clear image
	    stroke(0,0,0);
	    angle += 0.005;
	    rotateX(angle);
	    triangle(10,10,30,70,80,80);
	}	    

	</code>
	</para>
	<para id="collezioni_triangoli"><title>Collections of triangles
	</title> A set of triangles can be defined, similarly to what
	we did for points and segments, by the delimiters
	<code>beginShape()</code> and <code>endShape()</code>. Between
	them, the vertices of the triangles are listed by calls to the
	function <code>vertex()</code>. By the invocation
	<code>beginShape(TRIANGLES)</code> the vertices are taken in
	triples, each defining a triangle, while the invocation
	<code>beginShape(TRIANGLE_STRIP)</code> takes the vertices one
	after the other to define a strip mad of triangular facets. If
	the <code>vertex()</code> has three arguments, the vertices
	are located in the 3D space and the corresponding triangles
	identify planar surfaces in space.
	</para>
	<para id="quadrilateri"><title>Quadrilaterals</title> Rectangles
	are defined, in Processing, by the function
	<code>rect()</code> of four parameters, where the first couple
	specifies, by default, the position in the the 2D plane of the
	top-left corner, and the third and fourth parameters specify
	the width and height, respectively. The meaning of the first
	couple of parameters can be changed with the function
	<code>rectMode()</code>: <code>rectMode(CORNER)</code> gives
	the default positioning; <code>rectMode(CENTER)</code> gives
	the positioning of the center of the rectangle at the
	specified point; with the <code>rectMode(CORNERS)</code> the
	four parameters are interpreted as the coordinates of the
	top-left and bottom-right vertices, respectively.  A generic
	quadrilateral is defined by the coordinates of its four
	vertices, passed as parameters to the function
	<code>quad()</code>. It is important to notice that in 3D,
	while a triangle stays planar in any case, a quadruple of
	points does not necessarily lay on a plane. Viceversa, the
	quadrilaterals that are defined by 3D roto-translations of
	quadruples of 2D vertices, remain planar. Processing allows
	only eight parameters to be passed to <code>quad()</code>,
	thus forcing the definition of a quadrilateral as a quadruple
	of vertices in 2D.
	</para>
	<para id="collezioni_quadrilateri"><title>Collections of
	quadrilaterals</title> A set of quadrilaterals can be defined,
	similarly to what we saw for triangles, by the delimiters
	<code>beginShape()</code> and <code>endShape()</code>. Between
	them, vertices are listed by calls to the function
	<code>vertex()</code>. By using the invocation
	<code>beginShape(QUADS)</code> the vertices are taken in
	quadruples, each identifying a quadrilateral, while the
	invocation <code>beginShape(QUAD_STRIP)</code> takes the
	vertices one after the other to define a strip mad of
	quadrilateral facets. If the <code> vertex()</code> have three
	parameters, the planarity of the resulting faces is not
	ensured, and the resulting rendering can be misleading. For
	instance, by running the code
	  <code id="id1165052315268" display="block">
	    size(200,200,P3D);
	    lights();
	    beginShape(QUADS);
	    vertex(20,31, 33);
	    vertex(80, 40, 38);
	    vertex(75, 88, 50);
	    vertex(49, 85, 74);
	    endShape();
	  </code>
	  we realize that the quadrilateral is rendered as the
	  juxtaposition of two triangles belonging to different
	  planes.
	</para>
	<para id="poligoni"><title>Polygons</title> A generic polygon is
	defined as a set of vertices, and it has a surface that can be
	colored. In Processing the vertices are listed within a couple
	<code>beginShape(POLYGON);</code> - <code>endShape();</code>
	Actually, the polygon has to be intended in a generalized
	sense, as it is possible to use the
	<code>bezierVertex()</code> and <code>curveVertex()</code> to
	specify curved profiles. For instance, the reader may try to
	draw the moon:
	  <code id="id1165052315326" display="block">
	    fill(246, 168, 20);
	    beginShape(POLYGON); 
	    vertex(30, 20); 
	    bezierVertex(80, 10, 80, 75, 30, 75); 
	    bezierVertex(50, 70, 60, 25, 30, 20); 
	    endShape(); 
	  </code>
	</para>

	<para id="ellissi"><title>Ellipses</title> The function
	<code>ellipse()</code> draws an ellipse in the 2D plane. Its
	four parameters are interpreted, as in the case of
	<code>rect()</code>, as position followed by width and
	height. The position can be set in different ways according to
	the <code>ellipseMode()</code>, whose parameter can take
	values <code>CORNER, CORNERS, CENTER,
	CENTER_RADIUS</code>. The first couple of these possible
	values have to be referred to the rectangle that is
	circumscribed to the ellipse. </para>
      </section>
      <section id="treD">
	<title>3D</title> <para id="intro3D">Processing offers a very
	limited repertoire of 3D-object primitives, essentially only
	balls and boxes.</para> <para id="scatole"><title>Boxes</title>
	The function <code>box()</code> produces a cube when invoked
	with a single parameter (edge), a parallelepiped when invoked
	with three parameters (width, height, depth).  </para> <para id="palle"><title>Balls</title> The function
	<code>sphere()</code> produces, by an approximating
	polyhedron, a sphere whose radius is specified as a
	parameter.The function <code>sphereDetail()</code> can be used
	to specify the number of vertices of the polyhedron that
	approximates the ideal sphere.</para>
      </section>
    </section>
    <section id="stack">
      <title>The stack of transformations</title>
      <para id="stackp">
	A rotation or a translation can be imagined as operations that
	rotate or translate the Cartesian reference system. In other
	terms, after a <code>rotate()</code> or a
	<code>translate()</code> the following positioning operations
	of the objects will have a new coordinate system. When various
	objects are positioned in different ways in space, it is
	useful to keep trace of the coordinate systems that are set,
	one after the other. The data structure that is suited for
	containing such systems is the stack of transformations
	(<emphasis>matrix stack</emphasis>). With the function
	<code>pushMatrix()</code> the current coordinate system is put
	on top of the stack. On the other hand, to revert to the
	coordinate system before the last transformation, we have to
	call a <code>popMatrix()</code>. Actually, the stack contains
	the affine transformation matrices, according to what is
	dictated by <term url="http://www.opengl.org">OpenGL</term>
	and described in <link target-id="pillole_di_opengl"/>.
        </para>
      <example id="stack_example">
	<para id="stack_exp">
	In this example two objects are positioned in the 3D space: a
	planar square and a cube. The first <code>pushMatrix()</code> saves
	the coordinate system onto the stack, then some
	transformations are applied, and finally the square is
	drawn. To go back to the previous coordinate system and apply
	new transformations to position the cube, we apply a
	<code>popMatrix()</code>. Essentially, the
	<code>pushMatrix()</code> and <code>popMatrix()</code> determine the
	scope for the geometric positioning of an object.  
	</para>
	<code id="id1165052334588" display="block">
	float angle;

	void setup(){
          size(100, 100, P3D); 
	  int angle = 0;
	}

	void draw(){
	  background(200);
	  angle += 0.003;
	  pushMatrix();
	  translate(25,50);
	  rotateZ(angle);
	  rotateY(angle);
	  rectMode(CENTER);
	  rect(0,0,20,20);
	  popMatrix();
	  translate(75,50,-25);
	  rotateX(angle);
	  box(20);
	}

	</code>
      </example>
 
    </section>
    <section id="illuminazione">
      <title>Lighting</title> <para id="lucip"> The Processing lighting
      model echoes the model used in <term url="http://www.opengl.org">OpenGL</term>, that is the <term url="http://en.wikipedia.org/wiki/Phong_shading">Phong
      shading</term>. Such model is not physically justified, but it
      is particularly efficient. OpenGL considers as illuminated each
      polygon whose normal forms an acute angle with the direction of
      incoming light. This happens regardless of any masking
      objects. Therefore, shadows are not cast. OpenGL is said to
      use a local illumination model, since multiple reflections among
      surfaces and cast shadows are not automatically rendered.
      </para>
      <para id="types_of_light">An environmental light is available,
      which is not coming from any particular direction, and whose
      color is specified by the parameters of the activation call
      <code>ambientLight()</code>. A directional light source is set
      with the <code>directionalLight()</code>, whose parameters
      specify color and incoming direction. The method
      <code>lights()</code> activates a default combination of gray
      ambient light and directional light, the latter also gray,
      coming from the frontal direction. It is possible to set a point
      light source in a given point of space by the call
      <code>pointLight()</code>. Finally, the method
      <code>spotLight()</code> activates a light beam which can be
      controlled in its color, position, direction, aperture, and
      concentration around the axis. The exponent <m:math>
      <m:ci>e</m:ci>
	</m:math>
      tunes the falloff around the axis:
	<equation id="apertura">
	  <m:math>
	  <m:apply>
	    <m:power/>
	    <m:apply>
	      <m:cos/>
	      <m:ci>φ</m:ci>
	    </m:apply>
	    <m:ci>e</m:ci>
	  </m:apply>
	</m:math>
	</equation>
      </para>
      <para id="riflessioni">When hitting a planar surface, a directional light produces
      reflected light along several directions, depending on the
      surface properties. In the case of perfectly-diffusive (or
      <term>Lambertian</term>) surface, the light radiates evenly from
      the surface along all directions, with an intensity that is
      larger for incident directions closer to the surface normal.
      Vice versa, if the surface is perfectly reflecting, light is
      only reflected along the direction that is specularly symmetric
      (about the surface normal) to the incident direction. In OpenGL,
      to have some flexibility in defining the illumination, each
      source has the three illumination components: ambient, diffuse,
      and specular. These three components are separately defined and
      interact with the respective components that define the surface
      properties of objects. The colors defined in the methods
      <code>directionalLight()</code>, <code>pointLight()</code>, and
      <code>spotLight()</code> define the Lambertian component of
      illumination. The <code>lightSpecular()</code> specifies the
      color of the component of incoming light that is subject to
      specular reflection. </para>
      <para id="materiali">In Processing, the properties of surfaces are controlled by
      the methods <code>ambient()</code> (acting on the ambient
      component of incoming lights) and <code>specular()</code>
      (acting on the specular component). The function
      <code>shininess()</code> controls the concentration of the
      specularly-reflected beam, by a coefficient that acts similarly
      to the exponent of <link target-id="apertura"/>. The represented
      objects can also be considered as sources of light, and they can
      be assigned an emission light by the <code>emmissive()</code>
      call. However, the sources defined in this way do not illuminate
      the other objects on the scene.
      </para>
      <para id="decadimento">In OpenGL the point, spot, and ambient
      lights are attenuated with increasing distance, according to the
      model
	<equation id="attenuazione">
	  <m:math>
	  <m:apply>
	    <m:eq/>
	    <m:ci>attenuation</m:ci>
	    <m:apply>
	      <m:divide/>
	      <m:mn>1</m:mn>
	      <m:apply>
		<m:plus/>
		<m:ci>a</m:ci>
		<m:apply>
		  <m:times/>
		  <m:ci>b</m:ci>
		  <m:ci>d</m:ci>
		</m:apply>
		<m:apply>
		  <m:times/>
		  <m:ci>c</m:ci>
		  <m:apply>
		    <m:power/>
		    <m:ci>d</m:ci>
		    <m:mn>2</m:mn>
		  </m:apply>
		</m:apply>
	      </m:apply>
	    </m:apply>
	  </m:apply>
	</m:math>
	</equation> The method <code>ligthFalloff()</code> allows to
	specify the parameters <m:math> <m:ci>a</m:ci> </m:math>,
	<m:math> <m:ci>b</m:ci> </m:math>, and <m:math> <m:ci>c</m:ci>
	</m:math>.
</para>

      <example id="light_example">
	<para id="lightexp"> Here, a cube and a
	<code>QUAD_STRIP</code> are positioned in space and
	illuminated by a rotating source. Moreover, a soft fixed light
	is set. Notice the absence of shadows and the apparent
	planarity of surfaces in the <code>QUAD_STRIP</code>. </para>
	<code id="id1165052335000" display="block">float r;
float lightX, lightY, lightZ;

void setup() {
  size(400, 400, P3D);
  r = 0;
  ambient(180, 90, 0);
  specular(0, 0, 240);
  lightSpecular(200, 200, 200);   
  shininess(5);
}
  
void draw() {
  lightX = 100*sin(r/3) + width/2;
  lightY = 100*cos(r/3) + height/2;
  lightZ = 100*cos(r);
  background(0,0,0);
  noStroke(); 
  ambientLight(153, 102, 0);
  
  lightSpecular(0, 100, 200);
  pointLight(100, 180, 180, 
             lightX, lightY, lightZ);
  pushMatrix();
    translate(lightX, lightY, lightZ);
    emissive(100, 180, 180);
    sphere(4); //Put a little sphere where the light is
    emissive(0,0,0);
  popMatrix(); 
  pushMatrix();
    translate(width/2, height/2, 0);
    rotateX(PI/4);
    rotateY(PI/4); 
    box(100);
  popMatrix();
  pushMatrix();
    translate(width/4, height/2, 0);
    beginShape(QUAD_STRIP);
    vertex(10,13,8);
    vertex(13,90,13);
    vertex(65,76,44);
    vertex(95,106,44);
    vertex(97,20,70);
    vertex(109,70,80);
   endShape();
  popMatrix();
  r+=0.05;
}
	</code>
      </example>
    </section>

    <section id="projections">
      <title>Projections</title>
      <section id="perspective_projection">
	<title>Perspective projections</title> <para id="projectionp">A
	perspective projection is defined by a <term>center of
	projection</term> and a <term>plane of projection</term>. The
	<term>projector rays</term> connect the points in the scene
	with the center of projection, thus highlighting the
	corresponding points in the plane of projection. The <link target-id="projection2D"/> shows a section where the plane of
	projection produces a straight line whose abscissa is
	<m:math>
	    <m:apply>
	      <m:minus/>
	      <m:ci>d</m:ci>
	    </m:apply>
	  </m:math>, and the center of projection is in the origin.
	  <figure id="projection2D">
	    <media id="id1165052335113" alt=""><image src="perspective2D.png" mime-type="image/png"/></media>
	  </figure>
	  By similarity of two triangles it is easy to realize that
	    the point having ordinate <m:math> <m:ci>y</m:ci>
	    </m:math> gets projected onto the plane in the point
	    having ordinate <m:math>
	    <m:apply>
	      <m:eq/>
	    <m:msub>
	      <m:mi>y</m:mi>
	      <m:mn>p</m:mn>
	    </m:msub>
	      <m:apply>
		<m:minus/>
	      <m:apply>
		<m:divide/>
		<m:apply>
		  <m:times/>
		  <m:ci>y</m:ci>
		  <m:ci>d</m:ci>
		</m:apply>
		<m:ci>z</m:ci>
	      </m:apply>
	    </m:apply>
	      </m:apply>
	  </m:math>.
	</para>
	<para id="projection3Dp">
	  In general, the projection of a point having homogeneous coordinates
 	<m:math>
	  <m:vector>
	    <m:ci>x</m:ci>
	    <m:ci>y</m:ci>
	    <m:ci>z</m:ci>
	    <m:cn>1</m:cn>
	  </m:vector>
	</m:math>
	  onto a plane orthogonal to the <m:math>
	    <m:ci>z</m:ci> 
	  </m:math> axis and intersecting such axis in position <m:math>
	    <m:apply>
	      <m:minus/>
	      <m:ci>d</m:ci>
	    </m:apply>
	  </m:math> is obtained, in homogeneous coordinates, by
	  multiplication with the matrix
	  <m:math>
	    <m:matrix>
	      <m:matrixrow>
		<m:mn>1</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>1</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>1</m:mn>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		  <m:apply>
		    <m:minus/>
		  <m:apply>
		  <m:divide/>
		  <m:mn>1</m:mn>
		  <m:ci>d</m:ci>
		  </m:apply>
		  </m:apply>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	    </m:matrix>
	  </m:math>. The projected point becomes 	<m:math>
	  <m:vector>
	    <m:ci>x</m:ci>
	    <m:ci>y</m:ci>
	    <m:ci>z</m:ci>
		  <m:apply>
		    <m:minus/>
		  <m:apply>
		  <m:divide/>
		  <m:ci>z</m:ci>
		  <m:ci>d</m:ci>
		  </m:apply>
		  </m:apply>
	  </m:vector>
	  </m:math>, which can be normalized by multiplication of all
	  its element by <m:math>
		  <m:apply>
		    <m:minus/>
		  <m:apply>
		  <m:divide/>
		  <m:ci>d</m:ci>
		  <m:ci>z</m:ci>
		  </m:apply>
	      </m:apply>
	  </m:math>. As a result, we obtain <m:math>
	  <m:vector>
	      <m:apply>
		<m:minus/>
	      <m:apply>
		<m:divide/>
		<m:apply>
		  <m:times/>
		  <m:ci>x</m:ci>
		  <m:ci>d</m:ci>
		</m:apply>
		<m:ci>z</m:ci>
	      </m:apply>
	      </m:apply>
	      <m:apply>
		<m:minus/>
	      <m:apply>
		<m:divide/>
		<m:apply>
		  <m:times/>
		  <m:ci>y</m:ci>
		  <m:ci>d</m:ci>
		</m:apply>
		<m:ci>z</m:ci>
	      </m:apply>
	      </m:apply>
	      <m:apply>
		<m:minus/>
	    <m:ci>d</m:ci>
	      </m:apply>
	    <m:mn>1</m:mn>
	  </m:vector>
	  </m:math>
	</para>
      </section>
      <section id="parallel_views">
	<title>Parallel views</title>
	<para id="parallel_viewsp">
	  Parallel views are obtained by taking the center of
	  projection back to infinity (<m:math> <m:infinity/>
	  </m:math>). In this way, the projector rays are all
	  parallel.
	</para>
	<section id="orthographic_projection">
	  <title>Orthographic projection</title>
	  <para id="orthographic_projectionp">
	    The orthographic projection produces a class of parallel
	    views by casting projection rays orthogonal to the plane
	    of projection. If such plane is positioned orthogonally to
	    the <m:math> <m:ci>z</m:ci> </m:math> axis and passing by
	    the origin, the projection matrix turns out to be
	    particolarly simple:
	  <m:math>
	    <m:matrix>
	      <m:matrixrow>
		<m:mn>1</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>1</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>1</m:mn>
	      </m:matrixrow>
	    </m:matrix>
	  </m:math>.  Among orthographic projections, the
	    <term>axonometric projections</term> are based on the
	    possibility to measure the object along three orthogonal
	    axes, and on the orientation of the plane of projection
	    with respect to these axes. In particular, in the <link url="http://en.wikipedia.org/wiki/Isometric_projection">isometric
	    projection</link> the projections of the axes form angles
	    of <m:math>
	      <m:apply>
		<m:times/> <m:mn>120</m:mn>
	    <m:mi>°</m:mi> 
	      </m:apply>
	    </m:math>. The isometric projection has the property that
	    equal segments on the three axes remain equal when they
	    are projected onto the plane. In order to obtain the
	    isometric projection of an object whose main axes are
	    parallel to the coordinate axes, we can first rotate the
	    object by <m:math>
	      <m:apply>
		<m:times/>
		<m:mn>45 </m:mn> <m:mi>°</m:mi> </m:apply>
		</m:math> about the <m:math> <m:ci>y</m:ci> 
		</m:math> axis, and then rotate by
		<m:math>
	      <m:apply>
		<m:eq/>
		<m:apply>
		  <m:arctan/>
		  <m:apply>
		    <m:divide/>
		    <m:mn>1</m:mn>
		      <m:msqrt>
			<m:mn>2</m:mn>
		      </m:msqrt>
		  </m:apply>
		</m:apply>
		<m:apply>
		  <m:times/>
		<m:mn>35.264  </m:mn>
		<m:mi>°</m:mi>
		</m:apply>
	      </m:apply>
	    </m:math> about the  <m:math> <m:ci>x</m:ci>
	    </m:math> axis.
	  </para>
<!--	  <para id="orthop">
	    In processing, gli oggetti della scena sono visualizzati
	    con una proiezione ortografica se viene invocata la
	    primitiva <link
	      src="http://www.processing.org/reference/ortho_.html"><code>ortho()</code></link>.
	  </para> -->
	</section>
	<section id="oblique_projection">
	  <title>Oblique projection</title>
	  <para id="oblique_projectionp">We can talk about oblique projection every time the projector rays are oblique (non-orthogonal) to the projection plane. In order to deviate the projector rays from the normal direction by the angles  <m:math>
	    <m:ci>θ</m:ci> </m:math> and <m:math>
	    <m:ci>φ</m:ci> </m:math> we must use a projection matrix
 <m:math>
	    <m:matrix>
	      <m:matrixrow>
		<m:mn>1</m:mn>
		<m:mn>0</m:mn>
		  <m:apply>
		    <m:minus/>
		    <m:apply>
		      <m:tan/>
		      <m:ci>θ</m:ci>
		    </m:apply>
		  </m:apply>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>1</m:mn>
		  <m:apply>
		    <m:minus/>
		    <m:apply>
		      <m:tan/>
		      <m:ci>φ</m:ci>
		    </m:apply>
		  </m:apply>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
	      </m:matrixrow>
	      <m:matrixrow>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>0</m:mn>
		<m:mn>1</m:mn>
	      </m:matrixrow>
	    </m:matrix>
	  </m:math>
	  </para>
	</section>
      </section>
      <section id="shadow_casting">
	<title>Casting shadows</title>
	<para id="shadow_castingp">
	  As we have seen, Processing has a local illumination model,
	  thus being impossible to cast shadows directly. However, by
	  manipulating the affine transformation matrices we can cast
	  shadows onto planes. The method is called <term>flashing in
	  the eye</term>, thus meaning that the optical center of the
	  scene is moved to the point where the light source is
	  positioned, and then a perspective transformation is made,
	  with a plane of projection that coincides with the plane
	  where we want to cast the shadow on.
	</para>
	<example id="perspective_shadow">
	  <para id="perspective_shadowp">
	    The following program projects on the floor the shadow
	      produced by a light source positioned on the <m:math>
	      <m:ci>y</m:ci> </m:math> axis. The result is shown in
	      <link target-id="projectedShadow"/>
	 <figure id="projectedShadow">
	  <title>Casting a shadow</title>
	  <media id="id1165052335912" alt=""><image src="projectedShadow.png" mime-type="image/png"/></media>
	</figure>
	    <code id="id1165052335924" display="block">size(200, 200, P3D);
float centro = 100; 
float yp = 70; //floor (plane of projection) distance from center
float yl = 40; //height of light (center of projection) from center

translate(centro, centro, 0); //center the world on the cube

noFill();
box(yp*2); //draw of the room

pushMatrix();
  fill(250); noStroke();
  translate(0, -yl, 0); // move the virtual light bulb higher
  sphere(4); //draw of the light bulb
  stroke(10);
popMatrix();

pushMatrix(); //draw of the wireframe cube
  noFill();
  rotateY(PI/4); rotateX(PI/3);
  box(20);
popMatrix();

// SHADOW PROJECTION BY COMPOSITION 
// OF THREE TRANSFORMATIONS (the first one in 
// the code is the last one to be applied)

translate(0, -yl, 0); // shift of the light source and the floor back 
	              // to their place (see the translation below)

applyMatrix(1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 1/(yp+yl), 0, 0); // projection on the floor
                                 // moved down by yl

translate(0, yl, 0); // shift of the light source to center
                     // and of the floor down by yl

pushMatrix();    // draw of the cube that generate the shadow
  fill(120, 50); // by means of the above transformations
  noStroke();
  rotateY(PI/4); rotateX(PI/3);
  box(20);
popMatrix(); 
	    </code>
	  </para>
	</example>
      </section>
    </section>
    <section id="pillole_di_opengl">
      <title>Pills of OpenGL</title> <para id="openglp"> <term url="http://en.wikipedia.org/wiki/Opengl"> OpenGL</term> is a
      set of functions that allow the programmer to access the graphic
      system. Technically speaking, it is an <term url="http://en.wikipedia.org/wiki/API">Application Programming
      Interface (API)</term>. Its main scope is the graphic rendering
      of a scene populated by 3D objects and lights, from a given
      viewpoint. As far as the programmer is concerned, OpenGL allows
      to describe geometric objects and some of their properties, and
      to decide how such objects have to be illuminated and seen. As
      far as the implementation is concerned, OpenGL is based on the
      <emphasis>graphic pipeline </emphasis>, made of modules as
      reported in <link target-id="pipelineOpenGL"/>.  An excellent book
      on interactive graphics in OpenGL was written by <cite target-id="Angel"><cite-title>Angel</cite-title></cite>.
	<figure id="pipelineOpenGL">
	  <title>The OpenGL pipeline</title>
	  <media id="id1165052336038" alt=""><image src="pipelineOpenGL.png" mime-type="image/png"/></media>
	</figure>
</para>

      <para id="coordinate_transp"> In Processing (and in OpenGL), the
	programmer specifies the objects by means of world coordinates
	(<emphasis>standard coordinates</emphasis>). The
	<emphasis>model-view matrix</emphasis> is the transformation
	matrix used to go from standard coordinates to a space
	associated with the camera. This allows to change the camera
	viewpoint and orientation dynamically. In OpenGL this is done
	with the function <code>gluLookAt()</code>, which is
	reproduced in Processing by the <code>camera()</code>. The
	first triple of parameters identifies the position, in world
	coordinates, of the optical center of the camera (<term>eye
	point</term>). The second triple of parameters identifies a
	point where the camera is looking at  (<term>center of the
	scene</term>). The third triple of coordinates identifies a
	vector aimed at specifying the viewing vertical. For example,
	the program
	<code id="id1165052336108" display="block">  
	void setup() {
           size(100, 100, P3D); 
           noFill(); 
           frameRate(20);
        }

        void draw() {
           background(204); 
           camera(70.0, 35.0, 120.0, 50.0, 50.0, 0.0, 
             (float)mouseX /width, (float)mouseY /height, 0.0); 
           translate(50, 50, 0); 
           rotateX(-PI/6); 
           rotateY(PI/3); 
           box(45); 
        }
        
	</code>
        draws the <term>wireframe</term> of a cube and enables the
        dynamic rotation of the camera.
	</para>
        <para id="proiezp">
	The <emphasis>projection matrix</emphasis> is responsible for
	the projection on the viewing window, and this projection can
	be either parallel (orthographic) or perspective. The
	orthographic projection can be activated with the call
	<code>ortho()</code>. The perspective projection is the
	default one, but it can be explicitly activated with the call
	<code>perspective()</code>. Particular projections, such as
	the oblique ones, can be obtained by distortion of objects by
	application of the <code>applyMatrix()</code>. There is also
	the <emphasis>texture matrix</emphasis>, but textures are
	treated in another module.
      </para>
<!--      <para id="colori_openglp">
	Nella rappresentazione interna degli oggetti della scena, i
	vertici hanno un colore associato. Il colore di una superficie
	delimitata da un insieme di vertici viene reso per
	interpolazione bilineare.
      </para> -->
      <para id="matrici_opengl">
	For each type of matrix, OpenGL keeps a stack, the current
        matrix being on top. The stack data structure allows to save
        the state (by the <code>pushMatrix()</code>) before performing
        new transformations, or to remove the current state and
        activate previous states (by the
        <code>popMatrix()</code>). This is reflected in the Processing
        operations described in <link target-id="stack"/>. In OpenGL,
        the transformations are applied according to the sequence
	<list id="operazioni_matricil" list-type="enumerated">
	  <item> Push on the stack; </item> <item id="trasfid"> Apply
	    all desired transformations by multiplying by the
	    stack-top matrix; </item> <item> Draw the object (affected
	    by transformations);</item> <item> Pop from the
	    stack.</item>
	</list>
      </para>
      <para id="modelviewp">
       A <emphasis> viewport </emphasis> is a rectangular area of the
       display window. To go from the perspective projection plane to
       the viewport two steps are taken: (i) transformation into a 2 x
       2 window centered in the origin (<emphasis> normalized device
       coordinates </emphasis>) (ii) mapping the normalized window
       onto the viewport. Using the normalized device coordinates, the
       <term> clipping</term> operation, that is the elimination of
       objects or parts of objects that are not visible through the
       window, becomes trivial.  <code>screenX()</code>,
       <code>screenY()</code>, and <code>screenZ()</code> gives the
       X-Y coordinates produced by the viewport transformation and by
       the previous operators in the chain of <link target-id="pipelineOpenGL"/>.
      </para>
      <para id="frustum">The viewing <term>frustum</term> is the solid
      angle that encompasses the perspective projection, as shown in
      <link target-id="frustumf"/>. The objects (or their parts)
      belonging to the viewing volume are visualized, the remaining
      parts are subject to clipping.  In Processing (and in OpenGL)
      the frustum can be defined by positioning the six planes that
      define it (<code>frustum()</code>), or by specification of the
      vertical angle, the, <term>aspect ratio</term>, and the
      positions of the front and back planes
      (<code>perspective()</code>).  One may ask how the system
      removes the hidden faces, i.e., those faces that are masked by
      other faces in the viewing volume. OpenGL uses the <term url="http://en.wikipedia.org/wiki/Z_buffer">z-buffer</term>
      algorithm, which is supported by the graphic accelerators. The
      board memory stores a 2D memory area (the z-buffer)
      corresponding to the pixels of the viewing window, and
      containing depth values. Before a polygon gets projected on the
      viewing window the board checks if the pixels affected by such
      polygon have a depth value smaller than the polygon being
      drawn. If this is the case, it means that there is an object that masks the polygon.  </para>

      <figure id="frustumf">
	  <title>The viewing frustum</title>
	  <media id="id1165052336413" alt=""><image src="frustum.png" mime-type="image/png"/></media>
      </figure>

      <para id="processingBGraphicsp">
	Sophisticated geometric transformations are possible by direct
	 manipulation of the projection and model-view matrices. This
	 is possible, in Processing, starting from the unit matrix,
	 loaded with <code>resetMatrix()</code>, and proceeding by
	 matrix multiplies done with the <code>applyMatrix()</code>.
	<!-- Elaborazioni più
	 sofisticate di quelle ottenibili con le primitive Processing,
	 si possono ottenere utilizzando l'oggetto <code>g</code>,
	 istanza della classe <code>BGraphics</code>. Ad esempio, con
	 <code>g.transform()</code> si può imporre una matrice di
	 trasformazione, per fare uno scalamento obliquo
	 (<emphasis>shearing</emphasis>) o per proiettare ombre (si
	 veda l'esempio <code>shadows </code> in <link
	 src="http://www.cs.unm.edu/~cello/processing/"> I like
	 processing </link>). L'oggetto <code>g</code> è già stato
	 menzionato nella <cnxn target='illuminazione'/> a proposito
	 della regolazione delle sorgenti luminose. Purtroppo
	 l'utilizzazione della classe <code>BGraphics</code> non è
	 documentata, e per sapere quali metodi e variabili sono
	 disponibili bisogna riferirsi al <link
	 src="http://cvs.sourceforge.net/viewcvs.py/processing/cbagel/bgraphics.h">
	 codice sorgente</link>. -->
      </para>
      <exercise id="isometric_cube">
	<problem id="id1165052336462">
	  <para id="isometric_cubep">
	    Run and analyze the Processing code
	    <code id="id1165052336486" display="block">
	      size(200, 200, P3D);
	      println("Default matrix:"); printMatrix();
	      noFill(); 
	      ortho(-width/2, width/2, -height/2, height/2, -100, 100); 
	      translate(100, 100, 0); 
	      println("After translation:"); printMatrix();
	      rotateX(atan(1/sqrt(2))); 
	      println("After about-X rotation:"); printMatrix();
	      rotateY(PI/4); 
	      println("After about-Y rotation:"); printMatrix();
	      box(100); 
	    </code>
	    What is visualized and what it the kind of projection
	    used? How do you interpret the matrices printed out on the
	    console? Can one invert the order of rotations?
	  </para>
	</problem>
	<solution id="id1165052336503">
	  <para id="isometric_cubes">
	  The wireframe of a cube is visualized in isometric
	  projection.  The latter three matrices represent, one after
	  the other, the three operations of translation (to center
	  the cube to the window), rotation about the <m:math>
	  <m:ci>x</m:ci> </m:math> axis, and rotation about the
	  <m:math> <m:ci>y</m:ci> </m:math> axis. A sequence of two
	  rotations correspond to the product of two rotation
	  matrices, and the outcome is not order independent (product
	  is not commutative). The product of two rotation matrices
	  <m:math>
	      <m:apply>
		<m:times/>
		<m:msub>
		  <m:ci>R</m:ci>
		  <m:ci>x</m:ci>
		</m:msub>
		<m:msub>
		  <m:ci>R</m:ci>
		  <m:ci>y</m:ci>
		</m:msub>
	      </m:apply>
	    </m:math> correspond to performing the rotation about  <m:math>
	      <m:ci>y</m:ci>
	    </m:math> first, and then the rotation about <m:math>
	      <m:ci>x</m:ci>
	    </m:math>.
</para>
	</solution>
      </exercise>
      <exercise id="oblique_projectione">
	<problem id="id1165052336588">
	  <para id="oblique_projectionep">
	    Write a Processing program that performs the oblique
	    projection of a cube.
	  </para>
	</problem>
	<solution id="id1165052336606">
	  <para id="oblique_projectionesp"> For example: 
	    <code id="id1165052336621" display="block">
	    size(200, 200, P3D);
	    float theta = PI/6; 
	    float phi = PI/12;
	    noFill(); 
	    ortho(-width/2, width/2, -height/2, height/2, -100, 100); 
	    translate(100, 100, 0);
	    applyMatrix(1, 0, - tan(theta), 0,
	                0, 1, - tan(phi), 0,
                        0, 0, 0, 0,
                        0, 0, 0, 1);
	    box(100); 
	    </code>
	  </para>
	</solution>
      </exercise>
      <exercise id="ombre">
	<problem id="id1165052336645">
	  <para id="ombretp"> Visualize a cube that projects its
	  shadow on the floor, assuming that the light source is at
	  infinite distance (as it is the case, in practice, for the
	  sun).
	  </para>
	</problem>
	<solution id="id1165052336664">
	  <para id="ombresp">We do it similarly to <link target-id="perspective_shadow"/>, but the transformation is
	  orthographic:
	    <code id="id1165052336687" display="block">size(200, 200, P3D);
	      noFill();
	      translate(100, 100, 0);
	      pushMatrix();
	        rotateY(PI/4); rotateX(PI/3);
	        box(30);
	      popMatrix();
	      translate(0, 60, 0); //cast a shadow from infinity (sun)
	      applyMatrix(1, 0, 0, 0,
	                  0, 0, 0, 0,
                          0, 0, 1, 0,
                          0, 0, 0, 1); 
	      fill(150);
	      pushMatrix();
	      noStroke();
	      rotateY(PI/4); rotateX(PI/3);
	      box(30);
	      popMatrix(); 
	    </code>
	  </para>
	</solution>
      </exercise>
       
    </section>
  </content>

<bib:file>

<bib:entry id="Angel">
<bib:book>
<bib:author>Edward Angel</bib:author>
<bib:title>Interactive Computer Graphics: A Top-Down Approach With OPENGL primer package-2nd Edition</bib:title>
<bib:publisher>Prentice-Hall, Inc.</bib:publisher>
<bib:year>2001</bib:year>
</bib:book>
</bib:entry>
</bib:file>

</document>
