SlideShare a Scribd company logo
1 of 25
Download to read offline
Computer Graphics
in Java and Scala
Part 1
Continuous (Logical) and Discrete (Device) Coordinates
with a simple yet pleasing example involving concentric triangles
@philip_schwarz
slides by https://www.slideshare.net/pjschwarz
The idea of this series of decks is to have fun going through selected topics in books like
Computer Graphics for Java Programmers in order to
• learn (or reacquaint ourselves with) some well established computer graphics techniques
• see some of the Java code that the book uses to illustrate the techniques
• rewrite the code in Scala, hopefully encountering opportunities to use some functional
programming techniques
The subject of this first deck is
• the distinction between continuous (logical) and discrete (device) coordinates
• an example of using the technique to draw an interesting pattern involving triangles
https://www.linkedin.com/in/leen-ammeraal-b97b968/ https://profiles.utdallas.edu/kang.zhang
Leen Ammeraal Kang Zhang
@philip_schwarz
0 1 2 3 4 5 6 7 𝑥
0 ˙ ˙ ˙ ˙ ˙ ˙ ˙ ˙
1 ˙ ˙ ˙ ˙ ˙ ˙ ˙ ˙
2 ˙ ˙ ˙ ˙ ˙ ˙ ˙ ˙
3 ˙ ˙ ˙ ˙ ˙ ˙ ˙ ˙
𝑦
Fig 1.2 Pixels as
coordinates in a 8×4
canvas (with 𝐦𝐚𝐱𝐗 = 7
and 𝐦𝐚𝐱𝐘 = 3).
The following program lines in the paint method show how to obtain the canvas dimensions and how to
interpret them:
Dimension d = getSize();
int maxX = d.width – 1;
int maxY = d.height – 1;
The getSize method of Component (a superclass of Canvas) supplies us with the numbers of pixels on horizontal
and vertical lines of the canvas. Since we start counting at zero, the highest pixel numbers, maxX and maxY, on
these lines are one less than these numbers of pixels.
…
Figure 1.2 illustrates this for a very small canvas, which is only 8 pixels wide and 4 pixels high, showing a much
enlarged screen grid structure. It also shows that the line connecting the points 0,0 and 7,3 is approximated
by a set of eight pixels.
d.width = 8
d.height = 4
1.2 Logical Coordinates
The Direction of the y-axis
As Fig 1.2 shows, the origin of the device-coordinate systems lies at the top-left corner of the canvas, so that
the positive y-axis points downward.
This is reasonable for text output, that starts at the top and increases y as we go to the next line of text.
However, this direction of the y-axis is different from typical mathematical practice and therefore often
inconvenient in graphics applications.
For example, in a discussion about a line with a positive slope, we expect to go upward when moving along this
line from left to right.
Fortunately we can arrange for the positive y direction to be reversed by performing this simple
transformation:
𝑦! = 𝒎𝒂𝒙𝒀 − 𝑦
Fig 1.2
Continuous Versus Discrete Coordinates
Instead of the discrete (integer) coordinates at the lower, device-oriented level, we often wish to use
continuous (floating-point) coordinates at the higher, problem-oriented level. Other useful terms are device
and logical coordinates, respectively.
Writing conversion routines to compute device coordinates from the corresponding logical ones and vice versa
is a little bit tricky. We must be aware that there are two solutions to this problem: rounding and truncating,
even in the simple case in which increasing a logical coordinate by one results in increasing the device
coordinate also by one. We wish to write the following methods:
𝑖𝑋 𝑥 , 𝑖𝑌 𝑦 : 𝑐𝑜𝑛𝑣𝑒𝑟𝑡𝑖𝑛𝑔 𝑡ℎ𝑒 𝒍𝒐𝒈𝒊𝒄𝒂𝒍 𝒄𝒐𝒐𝒓𝒅𝒊𝒏𝒂𝒕𝒆𝒔 𝒙 𝑎𝑛𝑑 𝒚 𝑡𝑜 𝒅𝒆𝒗𝒊𝒄𝒆 𝒄𝒐𝒐𝒓𝒅𝒊𝒏𝒂𝒕𝒆𝒔;
𝑓𝑥 𝑋 , 𝑓𝑦 𝑌 : 𝑐𝑜𝑛𝑣𝑒𝑟𝑡𝑖𝑛𝑔 𝑡ℎ𝑒 𝒅𝒆𝒗𝒊𝒄𝒆 𝒄𝒐𝒐𝒓𝒅𝒊𝒏𝒂𝒕𝒆𝒔 𝑿 𝑎𝑛𝑑 𝒀 𝑡𝑜 𝒍𝒐𝒈𝒊𝒄𝒂𝒍 𝒄𝒐𝒐𝒓𝒅𝒊𝒏𝒂𝒕𝒆𝒔.
One may notice that we have used lower-case letters to represent logical coordinates and capital letters to
represent device coordinates. This will be the convention used throughout this book. With regard to x-
coordinates, the rounding solution could be:
int iX(float x) { return Math.round(x); }
float fx(int x) { return (float)x; }
For example, with this solution we have:
𝑖𝑋 2.8 = 3
𝑓𝑥 3 = 3.0
The i in 𝑖𝑋 is due to the function
returning an int. Similarly for
𝑓𝑥, which returns a float.
The truncating solution could be:
int iX(float x) { return (int)x; } // Not used in
float fx(int x) { return (float)x + 0.5F; } // this book
With these conversion functions, we would have
𝑖𝑋 2.8 = 2
𝑓𝑥 2 = 2.5
We will use the rounding solution throughout this book, since it is the better choice if logical coordinates
frequently happen to be integer values. In these cases the practice of truncating floating-point numbers will
often lead to worse results than those with rounding.
Apart from the above methods 𝑖𝑋 and 𝑓𝑥 (based on rounding), for x-coordinates, we need similar methods for
y-coordinates, taking into account the opposite direction of the two y-axes. At the bottom of the canvas, the
device y-coordinate is maxY, while the logical y-coordinate is 0, which may explain the two expressions of the
form maxY - … in the following methods:
int iX(float x) { return Math.round(x); }
int iY(float y) { return maxY - Math.round(y); }
float fx(int x) { return (float)x; }
float fy(int y) { return (float)(maxY - y); }
Figure 1.4 shows a fragment of a canvas, based on maxY=16.
The pixels are drawn as black dots, each placed at the center of a square of dashed lines, and the device coordinates
(X,Y) are placed between parentheses near each dot. For example, the pixel with device coordinates (8,2) at the
upper-right corner of this canvas fragment, has logical coordinates (8.0, 14.0). We have
iX(8.0) = Math.round(8.0) = 8
iY(14.0) = 16 - Math.round(14.0) = 2
fx(8) = (float)8 = 8.0
fy(2) = (float)(16 - 2) = 14.0
The dashed square around this dot denotes all points (x,y) satisfying:
7.5 ≤ 𝑥 < 8.5
13.5 ≤ 𝑦 < 14.5
All these points are converted to the pixel (8,2)
by our methods 𝑖𝑋 and 𝑖𝑌. Let us demonstrate
this way of converting floating-point logical
coordinates to integer device coordinates in a
program that begins by drawing an equilateral
triangle ABC, with the side AB at the bottom
and the point C at the top. Then using
q = 0.05
p = 1 − q = 0.95
We compute the new points A’, B’ and C’ near A, B and C
(5, 2) (6, 2) (7, 2) (8, 2)
(5, 3) (6, 3) (7, 3) (8, 3)
(5, 4) (6, 4) (7, 4) (8, 4)
5.0 6.0 7.0 8.0
14.0
13.0
12.0
Figure 1.4 Logical and device coordinates, based on maxY = 16
𝑦
𝑥
logical device
and lying on the sides AB, BC and CA respectively, writing:
xA1 = p * xA + q * xB;
yA1 = p * yA + q * yB;
xB1 = p * xB + q * xC;
yB1 = p * yB + q * yC;
xC1 = p * xC + q * xA;
yC1 = p * yC + q * yA;
We then draw the triangle A’B’C’, which is slightly smaller than ABC and turned a little counter-clockwise.
Applying the same principle to triangle A’B’C’ to obtain a third triangle A’’B’’C’’, and so on, until 50 triangles have
been drawn, the result will be as shown in Fig 1.5. If we change the dimensions of the window, new equilateral
triangles appear, again in the center of the canvas and with dimensions proportional to the size of this canvas.
Figure 1.5 Triangles, drawn inside each other
The next slide shows the Java
code for the whole program.
@philip_schwarz
import java.awt.*;
public class CvTriangles extends Canvas {
int maxX, maxY, minMaxXY, xCenter, yCenter;
void initgr() {
Dimension d = getSize();
maxX = d.width - 1; maxY = d.height - 1;
minMaxXY = Math.min(maxX, maxY);
xCenter = maxX / 2; yCenter = maxY / 2;
}
int iX(float x) { return Math.round(x); }
int iY(float y) { return maxY - Math.round(y); }
public void paint(Graphics g) {
initgr();
float side = 0.95F * minMaxXY, sideHalf = 0.5F * side,
h = sideHalf * (float) Math.sqrt(3),
xA, yA, xB, yB, xC, yC, xA1, yA1, xB1, yB1, xC1, yC1, p, q;
q = 0.05F; p = 1 - q;
xA = xCenter - sideHalf; yA = yCenter - 0.5F * h;
xB = xCenter + sideHalf; yB = yA;
xC = xCenter; yC = yCenter + 0.5F * h;
for (int i = 0; i < 50; i++) {
g.drawLine(iX(xA), iY(yA), iX(xB), iY(yB));
g.drawLine(iX(xB), iY(yB), iX(xC), iY(yC));
g.drawLine(iX(xC), iY(yC), iX(xA), iY(yA));
xA1 = p * xA + q * xB; yA1 = p * yA + q * yB;
xB1 = p * xB + q * xC; yB1 = p * yB + q * yC;
xC1 = p * xC + q * xA; yC1 = p * yC + q * yA;
xA = xA1; xB = xB1; xC = xC1;
yA = yA1; yB = yB1; yC = yC1;
}
}
}
// Triangles.java: This program draws 50
// triangles inside each other.
public class Triangles extends Frame {
public static void main(String[] args) {
new Triangles();
}
Triangles() {
super("Triangles: 50 triangles inside each other");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(600, 400);
add("Center", new CvTriangles());
setVisible(true);
}
}
Without floating-point logical coordinates and
with a y-axis pointing downward, this program
would have been less easy to write.
Let’s rewrite that Java code in Scala, beginning with the code section which given a starting
triangle, draws the triangle and then proceeds to repeatedly, first shrink and twist the
triangle, and then draw it, thus generating and drawing 49 more concentric triangles.
While the Java code uses a java.awt.Canvas, the Scala code uses a javax.swing.JPanel.
class TrianglesPanel extends JPanel:
…
override def paintComponent(g: Graphics): Unit =
…
LazyList.iterate(triangle)(shrinkAndTwist).take(50).foreach(draw)
public class CvTriangles extends Canvas {
…
public void paint(Graphics g) {
…
for (int i = 0; i < 50; i++) {
g.drawLine(iX(xA), iY(yA), iX(xB), iY(yB));
g.drawLine(iX(xB), iY(yB), iX(xC), iY(yC));
g.drawLine(iX(xC), iY(yC), iX(xA), iY(yA));
xA1 = p * xA + q * xB; yA1 = p * yA + q * yB;
xB1 = p * xB + q * xC; yB1 = p * yB + q * yC;
xC1 = p * xC + q * xA; yC1 = p * yC + q * yA;
xA = xA1; xB = xB1; xC = xC1;
yA = yA1; yB = yB1; yC = yC1;
}
}
}
Given an initial triangle, we are going to generate a lazy,
potentially infinite, sequence of triangles, in which each
triangle, with the exception of the first one, is the result of
shrinking and twisting the previous triangle.
We then take (materialise) the first 50 triangles of the
sequence and iterate through them, drawing each one in turn.
draw: Triangle => Unit
shrinkAndTwist: Triangle => Triangle
A triangle consists of three logical points (points with logical coordinates) A, B and C.
case class Point(x: Float, y: Float)
case class Triangle(a: Point, b: Point, c: Point)
Drawing a triangle amounts to drawing lines AB, BC and CA.
val draw: Triangle => Unit =
case Triangle(a, b, c) =>
drawLine(a, b)
drawLine(b, c)
drawLine(c, a)
To draw a line from logical point A to logical point B, we first compute the coordinates of the corresponding
device points, and then pass those coordinates to the drawLine method provided by the Graphics object.
def drawLine(a: Point, b: Point): Unit =
val (ax,ay) = a.deviceCoords(panelHeight)
val (bx,by) = b.deviceCoords(panelHeight)
g.drawLine(ax, ay, bx, by)
Here is how we enrich a logical point with a deviceCoords function that takes the logical coordinates of the
point and computes the corresponding device coordinates:
extension (p: Point)
def deviceCoords(panelHeight: Int): (Int, Int) =
(Math.round(p.x), panelHeight - Math.round(p.y))
The deviceCoords function is our Scala equivalent of Java functions iX and iY	:
int iX(float x) { return Math.round(x); }
int iY(float y) { return maxY - Math.round(y); }
LazyList.iterate(triangle)(shrinkAndTwist).take(50).foreach(draw)
xA1 = p * xA + q * xB; yA1 = p * yA + q * yB;
xB1 = p * xB + q * xC; yB1 = p * yB + q * yC;
xC1 = p * xC + q * xA; yC1 = p * yC + q * yA;
xA = xA1; xB = xB1; xC = xC1;
yA = yA1; yB = yB1; yC = yC1;
val shrinkAndTwist: Triangle => Triangle =
val q = 0.05F
val p = 1 - q
def combine(a: Point, b: Point) = Point(p * a.x + q * b.x, p * a.y + q * b.y)
{ case Triangle(a,b,c) => Triangle(combine(a,b), combine(b,c), combine(c,a)) }
As for the Java code that shrinks and twists a triangle, in our
Scala code, we encapsulate it in function shrinkAndTwist.
q = 0.05F; p = 1 - q;
float …
xA, yA, xB, yB, xC, yC, xA1,
yA1, xB1, yB1, xC1, yC1,
p, q;
@philip_schwarz
float side = 0.95F * minMaxXY, sideHalf = 0.5F * side,
h = sideHalf * (float) Math.sqrt(3),
…;
int maxX, maxY, minMaxXY, xCenter, yCenter;
void initgr() {
Dimension d = getSize();
maxX = d.width - 1; maxY = d.height - 1;
minMaxXY = Math.min(maxX, maxY);
xCenter = maxX / 2; yCenter = maxY / 2;
}
val panelSize: Dimension = getSize()
val panelWidth = panelSize.width - 1
val panelHeight = panelSize.height - 1
val panelCentre = Point(panelWidth / 2, panelHeight / 2)
val triangleSide = 0.95F * Math.min(panelWidth, panelHeight)
val triangleHeight = (0.5F * triangleSide) * Math.sqrt(3).toFloat
val triangle = makeTriangle(panelCentre,
triangleSide,
triangleHeight)
xA = xCenter - sideHalf; yA = yCenter - 0.5F * h;
xB = xCenter + sideHalf; yB = yA;
xC = xCenter; yC = yCenter + 0.5F * h;
As for the Java code that computes the first triangle from the dimensions
of the Canvas on which it is going to be drawn, here it is, together with the
corresponding Scala code, which draws on a JPanel.
object Triangle:
def apply(centre: Point, side: Float, height: Float): Triangle =
val Point(x,y) = centre
val halfSide = 0.5F * side
val bottomLeft = Point(x - halfSide, y - 0.5F * height)
val bottomRight = Point(x + halfSide, y - 0.5F * height)
val top = Point(x, y + 0.5F * height )
Triangle(bottomLeft,bottomRight,top)
class Triangles:
JFrame.setDefaultLookAndFeelDecorated(true)
val frame = new JFrame("Triangles: 50 triangles inside each other")
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
frame.setSize(600, 400)
frame.add(TrianglesPanel())
frame.setVisible(true)
@main def main: Unit =
// Create a panel on the event dispatching thread
SwingUtilities.invokeLater(
new Runnable():
def run: Unit = Triangles()
)
public class Triangles extends Frame {
public static void main(String[] args) {
new Triangles();
}
Triangles() {
super("Triangles: 50 triangles inside each other");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(600, 400);
add("Center", new CvTriangles());
setVisible(true);
}
}
And finally, let’s translate the rest of the
code, which creates the application’s frame.
Now let’s run the Scala program,
to verify that it works OK.
@philip_schwarz
Now let’s run the program again
after temporarily tweaking it so
that each side of a triangle is
drawn in a different colour.
And now let’s repeat that,
but with different colours
and a black background.
The next slide shows our Scala code in its
entirety, and the subsequent slide shows the
whole of the Java code again, for comparison.
class TrianglesPanel extends JPanel:
setBackground(Color.white)
override def paintComponent(g: Graphics): Unit =
super.paintComponent(g)
val panelSize: Dimension = getSize()
val panelWidth = panelSize.width - 1
val panelHeight = panelSize.height - 1
val panelCentre = Point(panelWidth / 2, panelHeight / 2)
val triangleSide: Float = 0.95F * Math.min(panelWidth, panelHeight)
val triangleHeight: Float = (0.5F * triangleSide) * Math.sqrt(3).toFloat
val shrinkAndTwist: Triangle => Triangle =
val q = 0.05F
val p = 1 - q
def combine(a: Point, b: Point) = Point(p * a.x + q * b.x, p * a.y + q * b.y)
{ case Triangle(a,b,c) => Triangle(combine(a,b), combine(b,c), combine(c,a)) }
def drawLine(a: Point, b: Point): Unit =
val (ax,ay) = a.deviceCoords(panelHeight)
val (bx,by) = b.deviceCoords(panelHeight)
g.drawLine(ax, ay, bx, by)
val draw: Triangle => Unit =
case Triangle(a, b, c) =>
drawLine(a, b)
drawLine(b, c)
drawLine(c, a)
val triangle = Triangle(panelCentre, triangleSide, triangleHeight)
LazyList.iterate(triangle)(shrinkAndTwist).take(50).foreach(draw)
class Triangles:
JFrame.setDefaultLookAndFeelDecorated(true)
val frame =
new JFrame("Triangles: 50 triangles inside each other")
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
frame.setSize(600, 400)
frame.add(TrianglesPanel())
frame.setVisible(true)
@main def main: Unit =
// Create a panel on the event dispatching thread
SwingUtilities.invokeLater(
new Runnable():
def run: Unit = Triangles()
)
case class Point(x: Float, y: Float)
extension (p: Point)
def deviceCoords(panelHeight: Int): (Int, Int) =
(Math.round(p.x), panelHeight - Math.round(p.y))
object Triangle:
def apply(centre: Point, side: Float, height: Float): Triangle =
val Point(x,y) = centre
val halfSide = 0.5F * side
val bottomLeft = Point(x - halfSide, y - 0.5F * height)
val bottomRight = Point(x + halfSide, y - 0.5F * height)
val top = Point(x, y + 0.5F * height )
Triangle(bottomLeft,bottomRight,top)
case class Triangle(a: Point, b: Point, c: Point)
public class CvTriangles extends Canvas {
int maxX, maxY, minMaxXY, xCenter, yCenter;
void initgr() {
Dimension d = getSize();
maxX = d.width - 1; maxY = d.height - 1;
minMaxXY = Math.min(maxX, maxY);
xCenter = maxX / 2; yCenter = maxY / 2;
}
int iX(float x) { return Math.round(x); }
int iY(float y) { return maxY - Math.round(y); }
public void paint(Graphics g) {
initgr();
float side = 0.95F * minMaxXY, sideHalf = 0.5F * side,
h = sideHalf * (float) Math.sqrt(3),
xA, yA, xB, yB, xC, yC, xA1, yA1, xB1, yB1, xC1, yC1, p, q;
q = 0.05F; p = 1 - q;
xA = xCenter - sideHalf; yA = yCenter - 0.5F * h;
xB = xCenter + sideHalf; yB = yA;
xC = xCenter; yC = yCenter + 0.5F * h;
for (int i = 0; i < 50; i++) {
g.drawLine(iX(xA), iY(yA), iX(xB), iY(yB));
g.drawLine(iX(xB), iY(yB), iX(xC), iY(yC));
g.drawLine(iX(xC), iY(yC), iX(xA), iY(yA));
xA1 = p * xA + q * xB; yA1 = p * yA + q * yB;
xB1 = p * xB + q * xC; yB1 = p * yB + q * yC;
xC1 = p * xC + q * xA; yC1 = p * yC + q * yA;
xA = xA1; xB = xB1; xC = xC1;
yA = yA1; yB = yB1; yC = yC1;
}
}
}
// Triangles.java: This program draws 50
// triangles inside each other.
public class Triangles extends Frame {
public static void main(String[] args) {
new Triangles();
}
Triangles() {
super("Triangles: 50 triangles inside each other");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(600, 400);
add("Center", new CvTriangles());
setVisible(true);
}
}
That’s all for now.
See you in Part 2.
@philip_schwarz

More Related Content

What's hot

Monad Laws Must be Checked
Monad Laws Must be CheckedMonad Laws Must be Checked
Monad Laws Must be CheckedPhilip Schwarz
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...Philip Schwarz
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Philip Schwarz
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsPhilip Schwarz
 
Arriving at monads by going from pure-function composition to effectful-funct...
Arriving at monads by going from pure-function composition to effectful-funct...Arriving at monads by going from pure-function composition to effectful-funct...
Arriving at monads by going from pure-function composition to effectful-funct...Philip Schwarz
 
Map, Filter and Reduce In Python
Map, Filter and Reduce In PythonMap, Filter and Reduce In Python
Map, Filter and Reduce In PythonSimplilearn
 
Left and Right Folds - Comparison of a mathematical definition and a programm...
Left and Right Folds- Comparison of a mathematical definition and a programm...Left and Right Folds- Comparison of a mathematical definition and a programm...
Left and Right Folds - Comparison of a mathematical definition and a programm...Philip Schwarz
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Philip Schwarz
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022Alexander Ioffe
 
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and ScalaSierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and ScalaPhilip Schwarz
 
Functional programming
Functional programmingFunctional programming
Functional programmingijcd
 
Point free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyondPoint free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyondPhilip Schwarz
 
Java Garbage Collection - How it works
Java Garbage Collection - How it worksJava Garbage Collection - How it works
Java Garbage Collection - How it worksMindfire Solutions
 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsPhilip Schwarz
 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersPiotr Paradziński
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackGaryCoady
 

What's hot (20)

Monad Laws Must be Checked
Monad Laws Must be CheckedMonad Laws Must be Checked
Monad Laws Must be Checked
 
Applicative Functor
Applicative FunctorApplicative Functor
Applicative Functor
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
Arriving at monads by going from pure-function composition to effectful-funct...
Arriving at monads by going from pure-function composition to effectful-funct...Arriving at monads by going from pure-function composition to effectful-funct...
Arriving at monads by going from pure-function composition to effectful-funct...
 
Map, Filter and Reduce In Python
Map, Filter and Reduce In PythonMap, Filter and Reduce In Python
Map, Filter and Reduce In Python
 
Left and Right Folds - Comparison of a mathematical definition and a programm...
Left and Right Folds- Comparison of a mathematical definition and a programm...Left and Right Folds- Comparison of a mathematical definition and a programm...
Left and Right Folds - Comparison of a mathematical definition and a programm...
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
 
ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022ZIO-Direct - Functional Scala 2022
ZIO-Direct - Functional Scala 2022
 
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and ScalaSierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
Point free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyondPoint free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyond
 
Java Garbage Collection - How it works
Java Garbage Collection - How it worksJava Garbage Collection - How it works
Java Garbage Collection - How it works
 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also Programs
 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly matters
 
Javapolymorphism
JavapolymorphismJavapolymorphism
Javapolymorphism
 
Numpy
NumpyNumpy
Numpy
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web Stack
 
Java Queue.pptx
Java Queue.pptxJava Queue.pptx
Java Queue.pptx
 

Similar to Computer Graphics in Java and Scala - Part 1

Computer Graphics in Java and Scala - Part 1b
Computer Graphics in Java and Scala - Part 1bComputer Graphics in Java and Scala - Part 1b
Computer Graphics in Java and Scala - Part 1bPhilip Schwarz
 
5HBC: How to Graph Implicit Relations Intro Packet!
5HBC: How to Graph Implicit Relations Intro Packet!5HBC: How to Graph Implicit Relations Intro Packet!
5HBC: How to Graph Implicit Relations Intro Packet!A Jorge Garcia
 
INTRODUCTION TO MATLAB presentation.pptx
INTRODUCTION TO MATLAB presentation.pptxINTRODUCTION TO MATLAB presentation.pptx
INTRODUCTION TO MATLAB presentation.pptxDevaraj Chilakala
 
Chapter 1: Linear Regression
Chapter 1: Linear RegressionChapter 1: Linear Regression
Chapter 1: Linear RegressionAkmelSyed
 
Matlab-free course by Mohd Esa
Matlab-free course by Mohd EsaMatlab-free course by Mohd Esa
Matlab-free course by Mohd EsaMohd Esa
 
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxSAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxanhlodge
 
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxSAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxagnesdcarey33086
 
Rasterisation of a circle by the bresenham algorithm
Rasterisation of a circle by the bresenham algorithmRasterisation of a circle by the bresenham algorithm
Rasterisation of a circle by the bresenham algorithmKALAIRANJANI21
 
Rasterisation of a circle by the bresenham algorithm
Rasterisation of a circle by the bresenham algorithmRasterisation of a circle by the bresenham algorithm
Rasterisation of a circle by the bresenham algorithmKALAIRANJANI21
 
Fundamentals of Multimedia - Vector Graphics.pdf
Fundamentals of Multimedia - Vector Graphics.pdfFundamentals of Multimedia - Vector Graphics.pdf
Fundamentals of Multimedia - Vector Graphics.pdfFatihahIrra
 
Computer graphic
Computer graphicComputer graphic
Computer graphicnusratema1
 
The Day You Finally Use Algebra: A 3D Math Primer
The Day You Finally Use Algebra: A 3D Math PrimerThe Day You Finally Use Algebra: A 3D Math Primer
The Day You Finally Use Algebra: A 3D Math PrimerJanie Clayton
 
Computer graphics lab manual
Computer graphics lab manualComputer graphics lab manual
Computer graphics lab manualAnkit Kumar
 
Computer Graphics Unit 2
Computer Graphics Unit 2Computer Graphics Unit 2
Computer Graphics Unit 2SanthiNivas
 

Similar to Computer Graphics in Java and Scala - Part 1 (20)

Computer Graphics in Java and Scala - Part 1b
Computer Graphics in Java and Scala - Part 1bComputer Graphics in Java and Scala - Part 1b
Computer Graphics in Java and Scala - Part 1b
 
5HBC: How to Graph Implicit Relations Intro Packet!
5HBC: How to Graph Implicit Relations Intro Packet!5HBC: How to Graph Implicit Relations Intro Packet!
5HBC: How to Graph Implicit Relations Intro Packet!
 
INTRODUCTION TO MATLAB presentation.pptx
INTRODUCTION TO MATLAB presentation.pptxINTRODUCTION TO MATLAB presentation.pptx
INTRODUCTION TO MATLAB presentation.pptx
 
Lesson 3
Lesson 3Lesson 3
Lesson 3
 
MATLABgraphPlotting.pptx
MATLABgraphPlotting.pptxMATLABgraphPlotting.pptx
MATLABgraphPlotting.pptx
 
Chapter 1: Linear Regression
Chapter 1: Linear RegressionChapter 1: Linear Regression
Chapter 1: Linear Regression
 
raster algorithm.pdf
raster algorithm.pdfraster algorithm.pdf
raster algorithm.pdf
 
Matlab-free course by Mohd Esa
Matlab-free course by Mohd EsaMatlab-free course by Mohd Esa
Matlab-free course by Mohd Esa
 
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxSAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
 
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxSAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
 
Rasterisation of a circle by the bresenham algorithm
Rasterisation of a circle by the bresenham algorithmRasterisation of a circle by the bresenham algorithm
Rasterisation of a circle by the bresenham algorithm
 
Rasterisation of a circle by the bresenham algorithm
Rasterisation of a circle by the bresenham algorithmRasterisation of a circle by the bresenham algorithm
Rasterisation of a circle by the bresenham algorithm
 
Fundamentals of Multimedia - Vector Graphics.pdf
Fundamentals of Multimedia - Vector Graphics.pdfFundamentals of Multimedia - Vector Graphics.pdf
Fundamentals of Multimedia - Vector Graphics.pdf
 
Computer graphic
Computer graphicComputer graphic
Computer graphic
 
bobok
bobokbobok
bobok
 
The Day You Finally Use Algebra: A 3D Math Primer
The Day You Finally Use Algebra: A 3D Math PrimerThe Day You Finally Use Algebra: A 3D Math Primer
The Day You Finally Use Algebra: A 3D Math Primer
 
presentation.pptx
presentation.pptxpresentation.pptx
presentation.pptx
 
Computer graphics notes
Computer graphics notesComputer graphics notes
Computer graphics notes
 
Computer graphics lab manual
Computer graphics lab manualComputer graphics lab manual
Computer graphics lab manual
 
Computer Graphics Unit 2
Computer Graphics Unit 2Computer Graphics Unit 2
Computer Graphics Unit 2
 

More from Philip Schwarz

Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesPhilip Schwarz
 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesPhilip Schwarz
 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesPhilip Schwarz
 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three ApproachesPhilip Schwarz
 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsPhilip Schwarz
 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaPhilip Schwarz
 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaPhilip Schwarz
 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaPhilip Schwarz
 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsPhilip Schwarz
 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Philip Schwarz
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...Philip Schwarz
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsPhilip Schwarz
 
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Philip Schwarz
 
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Philip Schwarz
 
The Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsThe Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsPhilip Schwarz
 
The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1Philip Schwarz
 
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Philip Schwarz
 

More from Philip Schwarz (20)

Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a series
 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a series
 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a series
 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three Approaches
 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in Scala
 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in Scala
 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in Scala
 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets Cats
 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axioms
 
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
 
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
 
The Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsThe Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor corrections
 
The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1
 
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
 

Recently uploaded

oracle 23c new features for developer and dba
oracle 23c new features for developer and dbaoracle 23c new features for developer and dba
oracle 23c new features for developer and dbaRemote DBA Services
 
SPSS Statistics - Encrypting a Syntax File in IBM SPSS Statistics.pptx
SPSS Statistics - Encrypting a Syntax File in IBM SPSS Statistics.pptxSPSS Statistics - Encrypting a Syntax File in IBM SPSS Statistics.pptx
SPSS Statistics - Encrypting a Syntax File in IBM SPSS Statistics.pptxVersion 1 Analytics
 
AmsterdamJUG April 2024 - Going serverless with Quarkus GraalVM native images...
AmsterdamJUG April 2024 - Going serverless with Quarkus GraalVM native images...AmsterdamJUG April 2024 - Going serverless with Quarkus GraalVM native images...
AmsterdamJUG April 2024 - Going serverless with Quarkus GraalVM native images...Bert Jan Schrijver
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxSasikiranMarri
 
Explore the Three Main Types of Logistics - Inbound Logistics, Outbound Logis...
Explore the Three Main Types of Logistics - Inbound Logistics, Outbound Logis...Explore the Three Main Types of Logistics - Inbound Logistics, Outbound Logis...
Explore the Three Main Types of Logistics - Inbound Logistics, Outbound Logis...Piyovi
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorTier1 app
 
ManageIQ - Sprint 234 Review - Slide Deck
ManageIQ - Sprint 234 Review - Slide DeckManageIQ - Sprint 234 Review - Slide Deck
ManageIQ - Sprint 234 Review - Slide DeckManageIQ
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfkalichargn70th171
 
The State of the Green IT at the beginning of 2024
The State of the Green IT at the beginning of 2024The State of the Green IT at the beginning of 2024
The State of the Green IT at the beginning of 2024Artur Skowroński
 
full course of software engineering mid term.pdf
full course of software engineering mid term.pdffull course of software engineering mid term.pdf
full course of software engineering mid term.pdfAbdul salam
 
Effort Estimation Techniques used in Software Projects
Effort Estimation Techniques used in Software ProjectsEffort Estimation Techniques used in Software Projects
Effort Estimation Techniques used in Software ProjectsDEEPRAJ PATHAK
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...OnePlan Solutions
 
Tech Tuesday Slides - Getting Started with the Portfolio Module.
Tech Tuesday Slides - Getting Started with the Portfolio Module.Tech Tuesday Slides - Getting Started with the Portfolio Module.
Tech Tuesday Slides - Getting Started with the Portfolio Module.OnePlan Solutions
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolsosttopstonverter
 
Chapter -5 Agile Testing types and its examples.pptx
Chapter -5 Agile Testing types and its examples.pptxChapter -5 Agile Testing types and its examples.pptx
Chapter -5 Agile Testing types and its examples.pptxManishaPatil932723
 
Reliable from-source builds (Qshare 28 Nov 2023).pdf
Reliable from-source builds (Qshare 28 Nov 2023).pdfReliable from-source builds (Qshare 28 Nov 2023).pdf
Reliable from-source builds (Qshare 28 Nov 2023).pdfRalf Gommers
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldRoberto Pérez Alcolea
 
Leveraging the Expertise of a Social Media Fraud Analyst to Safeguard Brand R...
Leveraging the Expertise of a Social Media Fraud Analyst to Safeguard Brand R...Leveraging the Expertise of a Social Media Fraud Analyst to Safeguard Brand R...
Leveraging the Expertise of a Social Media Fraud Analyst to Safeguard Brand R...Milind Agarwal
 
Santander Stream Processing with Apache Flink
Santander Stream Processing with Apache FlinkSantander Stream Processing with Apache Flink
Santander Stream Processing with Apache Flinkconfluent
 
Revolutionize Your Video Editing with InVideo.io: A Comprehensive Review
Revolutionize Your Video Editing with InVideo.io: A Comprehensive ReviewRevolutionize Your Video Editing with InVideo.io: A Comprehensive Review
Revolutionize Your Video Editing with InVideo.io: A Comprehensive Reviewjw364beach
 

Recently uploaded (20)

oracle 23c new features for developer and dba
oracle 23c new features for developer and dbaoracle 23c new features for developer and dba
oracle 23c new features for developer and dba
 
SPSS Statistics - Encrypting a Syntax File in IBM SPSS Statistics.pptx
SPSS Statistics - Encrypting a Syntax File in IBM SPSS Statistics.pptxSPSS Statistics - Encrypting a Syntax File in IBM SPSS Statistics.pptx
SPSS Statistics - Encrypting a Syntax File in IBM SPSS Statistics.pptx
 
AmsterdamJUG April 2024 - Going serverless with Quarkus GraalVM native images...
AmsterdamJUG April 2024 - Going serverless with Quarkus GraalVM native images...AmsterdamJUG April 2024 - Going serverless with Quarkus GraalVM native images...
AmsterdamJUG April 2024 - Going serverless with Quarkus GraalVM native images...
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
 
Explore the Three Main Types of Logistics - Inbound Logistics, Outbound Logis...
Explore the Three Main Types of Logistics - Inbound Logistics, Outbound Logis...Explore the Three Main Types of Logistics - Inbound Logistics, Outbound Logis...
Explore the Three Main Types of Logistics - Inbound Logistics, Outbound Logis...
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryError
 
ManageIQ - Sprint 234 Review - Slide Deck
ManageIQ - Sprint 234 Review - Slide DeckManageIQ - Sprint 234 Review - Slide Deck
ManageIQ - Sprint 234 Review - Slide Deck
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
 
The State of the Green IT at the beginning of 2024
The State of the Green IT at the beginning of 2024The State of the Green IT at the beginning of 2024
The State of the Green IT at the beginning of 2024
 
full course of software engineering mid term.pdf
full course of software engineering mid term.pdffull course of software engineering mid term.pdf
full course of software engineering mid term.pdf
 
Effort Estimation Techniques used in Software Projects
Effort Estimation Techniques used in Software ProjectsEffort Estimation Techniques used in Software Projects
Effort Estimation Techniques used in Software Projects
 
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
 
Tech Tuesday Slides - Getting Started with the Portfolio Module.
Tech Tuesday Slides - Getting Started with the Portfolio Module.Tech Tuesday Slides - Getting Started with the Portfolio Module.
Tech Tuesday Slides - Getting Started with the Portfolio Module.
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration tools
 
Chapter -5 Agile Testing types and its examples.pptx
Chapter -5 Agile Testing types and its examples.pptxChapter -5 Agile Testing types and its examples.pptx
Chapter -5 Agile Testing types and its examples.pptx
 
Reliable from-source builds (Qshare 28 Nov 2023).pdf
Reliable from-source builds (Qshare 28 Nov 2023).pdfReliable from-source builds (Qshare 28 Nov 2023).pdf
Reliable from-source builds (Qshare 28 Nov 2023).pdf
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
Leveraging the Expertise of a Social Media Fraud Analyst to Safeguard Brand R...
Leveraging the Expertise of a Social Media Fraud Analyst to Safeguard Brand R...Leveraging the Expertise of a Social Media Fraud Analyst to Safeguard Brand R...
Leveraging the Expertise of a Social Media Fraud Analyst to Safeguard Brand R...
 
Santander Stream Processing with Apache Flink
Santander Stream Processing with Apache FlinkSantander Stream Processing with Apache Flink
Santander Stream Processing with Apache Flink
 
Revolutionize Your Video Editing with InVideo.io: A Comprehensive Review
Revolutionize Your Video Editing with InVideo.io: A Comprehensive ReviewRevolutionize Your Video Editing with InVideo.io: A Comprehensive Review
Revolutionize Your Video Editing with InVideo.io: A Comprehensive Review
 

Computer Graphics in Java and Scala - Part 1

  • 1. Computer Graphics in Java and Scala Part 1 Continuous (Logical) and Discrete (Device) Coordinates with a simple yet pleasing example involving concentric triangles @philip_schwarz slides by https://www.slideshare.net/pjschwarz
  • 2. The idea of this series of decks is to have fun going through selected topics in books like Computer Graphics for Java Programmers in order to • learn (or reacquaint ourselves with) some well established computer graphics techniques • see some of the Java code that the book uses to illustrate the techniques • rewrite the code in Scala, hopefully encountering opportunities to use some functional programming techniques The subject of this first deck is • the distinction between continuous (logical) and discrete (device) coordinates • an example of using the technique to draw an interesting pattern involving triangles https://www.linkedin.com/in/leen-ammeraal-b97b968/ https://profiles.utdallas.edu/kang.zhang Leen Ammeraal Kang Zhang @philip_schwarz
  • 3. 0 1 2 3 4 5 6 7 𝑥 0 ˙ ˙ ˙ ˙ ˙ ˙ ˙ ˙ 1 ˙ ˙ ˙ ˙ ˙ ˙ ˙ ˙ 2 ˙ ˙ ˙ ˙ ˙ ˙ ˙ ˙ 3 ˙ ˙ ˙ ˙ ˙ ˙ ˙ ˙ 𝑦 Fig 1.2 Pixels as coordinates in a 8×4 canvas (with 𝐦𝐚𝐱𝐗 = 7 and 𝐦𝐚𝐱𝐘 = 3). The following program lines in the paint method show how to obtain the canvas dimensions and how to interpret them: Dimension d = getSize(); int maxX = d.width – 1; int maxY = d.height – 1; The getSize method of Component (a superclass of Canvas) supplies us with the numbers of pixels on horizontal and vertical lines of the canvas. Since we start counting at zero, the highest pixel numbers, maxX and maxY, on these lines are one less than these numbers of pixels. … Figure 1.2 illustrates this for a very small canvas, which is only 8 pixels wide and 4 pixels high, showing a much enlarged screen grid structure. It also shows that the line connecting the points 0,0 and 7,3 is approximated by a set of eight pixels. d.width = 8 d.height = 4
  • 4. 1.2 Logical Coordinates The Direction of the y-axis As Fig 1.2 shows, the origin of the device-coordinate systems lies at the top-left corner of the canvas, so that the positive y-axis points downward. This is reasonable for text output, that starts at the top and increases y as we go to the next line of text. However, this direction of the y-axis is different from typical mathematical practice and therefore often inconvenient in graphics applications. For example, in a discussion about a line with a positive slope, we expect to go upward when moving along this line from left to right. Fortunately we can arrange for the positive y direction to be reversed by performing this simple transformation: 𝑦! = 𝒎𝒂𝒙𝒀 − 𝑦 Fig 1.2
  • 5. Continuous Versus Discrete Coordinates Instead of the discrete (integer) coordinates at the lower, device-oriented level, we often wish to use continuous (floating-point) coordinates at the higher, problem-oriented level. Other useful terms are device and logical coordinates, respectively. Writing conversion routines to compute device coordinates from the corresponding logical ones and vice versa is a little bit tricky. We must be aware that there are two solutions to this problem: rounding and truncating, even in the simple case in which increasing a logical coordinate by one results in increasing the device coordinate also by one. We wish to write the following methods: 𝑖𝑋 𝑥 , 𝑖𝑌 𝑦 : 𝑐𝑜𝑛𝑣𝑒𝑟𝑡𝑖𝑛𝑔 𝑡ℎ𝑒 𝒍𝒐𝒈𝒊𝒄𝒂𝒍 𝒄𝒐𝒐𝒓𝒅𝒊𝒏𝒂𝒕𝒆𝒔 𝒙 𝑎𝑛𝑑 𝒚 𝑡𝑜 𝒅𝒆𝒗𝒊𝒄𝒆 𝒄𝒐𝒐𝒓𝒅𝒊𝒏𝒂𝒕𝒆𝒔; 𝑓𝑥 𝑋 , 𝑓𝑦 𝑌 : 𝑐𝑜𝑛𝑣𝑒𝑟𝑡𝑖𝑛𝑔 𝑡ℎ𝑒 𝒅𝒆𝒗𝒊𝒄𝒆 𝒄𝒐𝒐𝒓𝒅𝒊𝒏𝒂𝒕𝒆𝒔 𝑿 𝑎𝑛𝑑 𝒀 𝑡𝑜 𝒍𝒐𝒈𝒊𝒄𝒂𝒍 𝒄𝒐𝒐𝒓𝒅𝒊𝒏𝒂𝒕𝒆𝒔. One may notice that we have used lower-case letters to represent logical coordinates and capital letters to represent device coordinates. This will be the convention used throughout this book. With regard to x- coordinates, the rounding solution could be: int iX(float x) { return Math.round(x); } float fx(int x) { return (float)x; } For example, with this solution we have: 𝑖𝑋 2.8 = 3 𝑓𝑥 3 = 3.0 The i in 𝑖𝑋 is due to the function returning an int. Similarly for 𝑓𝑥, which returns a float.
  • 6. The truncating solution could be: int iX(float x) { return (int)x; } // Not used in float fx(int x) { return (float)x + 0.5F; } // this book With these conversion functions, we would have 𝑖𝑋 2.8 = 2 𝑓𝑥 2 = 2.5 We will use the rounding solution throughout this book, since it is the better choice if logical coordinates frequently happen to be integer values. In these cases the practice of truncating floating-point numbers will often lead to worse results than those with rounding. Apart from the above methods 𝑖𝑋 and 𝑓𝑥 (based on rounding), for x-coordinates, we need similar methods for y-coordinates, taking into account the opposite direction of the two y-axes. At the bottom of the canvas, the device y-coordinate is maxY, while the logical y-coordinate is 0, which may explain the two expressions of the form maxY - … in the following methods: int iX(float x) { return Math.round(x); } int iY(float y) { return maxY - Math.round(y); } float fx(int x) { return (float)x; } float fy(int y) { return (float)(maxY - y); }
  • 7. Figure 1.4 shows a fragment of a canvas, based on maxY=16. The pixels are drawn as black dots, each placed at the center of a square of dashed lines, and the device coordinates (X,Y) are placed between parentheses near each dot. For example, the pixel with device coordinates (8,2) at the upper-right corner of this canvas fragment, has logical coordinates (8.0, 14.0). We have iX(8.0) = Math.round(8.0) = 8 iY(14.0) = 16 - Math.round(14.0) = 2 fx(8) = (float)8 = 8.0 fy(2) = (float)(16 - 2) = 14.0 The dashed square around this dot denotes all points (x,y) satisfying: 7.5 ≤ 𝑥 < 8.5 13.5 ≤ 𝑦 < 14.5 All these points are converted to the pixel (8,2) by our methods 𝑖𝑋 and 𝑖𝑌. Let us demonstrate this way of converting floating-point logical coordinates to integer device coordinates in a program that begins by drawing an equilateral triangle ABC, with the side AB at the bottom and the point C at the top. Then using q = 0.05 p = 1 − q = 0.95 We compute the new points A’, B’ and C’ near A, B and C (5, 2) (6, 2) (7, 2) (8, 2) (5, 3) (6, 3) (7, 3) (8, 3) (5, 4) (6, 4) (7, 4) (8, 4) 5.0 6.0 7.0 8.0 14.0 13.0 12.0 Figure 1.4 Logical and device coordinates, based on maxY = 16 𝑦 𝑥 logical device
  • 8. and lying on the sides AB, BC and CA respectively, writing: xA1 = p * xA + q * xB; yA1 = p * yA + q * yB; xB1 = p * xB + q * xC; yB1 = p * yB + q * yC; xC1 = p * xC + q * xA; yC1 = p * yC + q * yA; We then draw the triangle A’B’C’, which is slightly smaller than ABC and turned a little counter-clockwise. Applying the same principle to triangle A’B’C’ to obtain a third triangle A’’B’’C’’, and so on, until 50 triangles have been drawn, the result will be as shown in Fig 1.5. If we change the dimensions of the window, new equilateral triangles appear, again in the center of the canvas and with dimensions proportional to the size of this canvas. Figure 1.5 Triangles, drawn inside each other
  • 9. The next slide shows the Java code for the whole program. @philip_schwarz
  • 10. import java.awt.*; public class CvTriangles extends Canvas { int maxX, maxY, minMaxXY, xCenter, yCenter; void initgr() { Dimension d = getSize(); maxX = d.width - 1; maxY = d.height - 1; minMaxXY = Math.min(maxX, maxY); xCenter = maxX / 2; yCenter = maxY / 2; } int iX(float x) { return Math.round(x); } int iY(float y) { return maxY - Math.round(y); } public void paint(Graphics g) { initgr(); float side = 0.95F * minMaxXY, sideHalf = 0.5F * side, h = sideHalf * (float) Math.sqrt(3), xA, yA, xB, yB, xC, yC, xA1, yA1, xB1, yB1, xC1, yC1, p, q; q = 0.05F; p = 1 - q; xA = xCenter - sideHalf; yA = yCenter - 0.5F * h; xB = xCenter + sideHalf; yB = yA; xC = xCenter; yC = yCenter + 0.5F * h; for (int i = 0; i < 50; i++) { g.drawLine(iX(xA), iY(yA), iX(xB), iY(yB)); g.drawLine(iX(xB), iY(yB), iX(xC), iY(yC)); g.drawLine(iX(xC), iY(yC), iX(xA), iY(yA)); xA1 = p * xA + q * xB; yA1 = p * yA + q * yB; xB1 = p * xB + q * xC; yB1 = p * yB + q * yC; xC1 = p * xC + q * xA; yC1 = p * yC + q * yA; xA = xA1; xB = xB1; xC = xC1; yA = yA1; yB = yB1; yC = yC1; } } } // Triangles.java: This program draws 50 // triangles inside each other. public class Triangles extends Frame { public static void main(String[] args) { new Triangles(); } Triangles() { super("Triangles: 50 triangles inside each other"); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setSize(600, 400); add("Center", new CvTriangles()); setVisible(true); } } Without floating-point logical coordinates and with a y-axis pointing downward, this program would have been less easy to write.
  • 11. Let’s rewrite that Java code in Scala, beginning with the code section which given a starting triangle, draws the triangle and then proceeds to repeatedly, first shrink and twist the triangle, and then draw it, thus generating and drawing 49 more concentric triangles. While the Java code uses a java.awt.Canvas, the Scala code uses a javax.swing.JPanel. class TrianglesPanel extends JPanel: … override def paintComponent(g: Graphics): Unit = … LazyList.iterate(triangle)(shrinkAndTwist).take(50).foreach(draw) public class CvTriangles extends Canvas { … public void paint(Graphics g) { … for (int i = 0; i < 50; i++) { g.drawLine(iX(xA), iY(yA), iX(xB), iY(yB)); g.drawLine(iX(xB), iY(yB), iX(xC), iY(yC)); g.drawLine(iX(xC), iY(yC), iX(xA), iY(yA)); xA1 = p * xA + q * xB; yA1 = p * yA + q * yB; xB1 = p * xB + q * xC; yB1 = p * yB + q * yC; xC1 = p * xC + q * xA; yC1 = p * yC + q * yA; xA = xA1; xB = xB1; xC = xC1; yA = yA1; yB = yB1; yC = yC1; } } } Given an initial triangle, we are going to generate a lazy, potentially infinite, sequence of triangles, in which each triangle, with the exception of the first one, is the result of shrinking and twisting the previous triangle. We then take (materialise) the first 50 triangles of the sequence and iterate through them, drawing each one in turn. draw: Triangle => Unit shrinkAndTwist: Triangle => Triangle
  • 12. A triangle consists of three logical points (points with logical coordinates) A, B and C. case class Point(x: Float, y: Float) case class Triangle(a: Point, b: Point, c: Point) Drawing a triangle amounts to drawing lines AB, BC and CA. val draw: Triangle => Unit = case Triangle(a, b, c) => drawLine(a, b) drawLine(b, c) drawLine(c, a) To draw a line from logical point A to logical point B, we first compute the coordinates of the corresponding device points, and then pass those coordinates to the drawLine method provided by the Graphics object. def drawLine(a: Point, b: Point): Unit = val (ax,ay) = a.deviceCoords(panelHeight) val (bx,by) = b.deviceCoords(panelHeight) g.drawLine(ax, ay, bx, by) Here is how we enrich a logical point with a deviceCoords function that takes the logical coordinates of the point and computes the corresponding device coordinates: extension (p: Point) def deviceCoords(panelHeight: Int): (Int, Int) = (Math.round(p.x), panelHeight - Math.round(p.y)) The deviceCoords function is our Scala equivalent of Java functions iX and iY : int iX(float x) { return Math.round(x); } int iY(float y) { return maxY - Math.round(y); } LazyList.iterate(triangle)(shrinkAndTwist).take(50).foreach(draw)
  • 13. xA1 = p * xA + q * xB; yA1 = p * yA + q * yB; xB1 = p * xB + q * xC; yB1 = p * yB + q * yC; xC1 = p * xC + q * xA; yC1 = p * yC + q * yA; xA = xA1; xB = xB1; xC = xC1; yA = yA1; yB = yB1; yC = yC1; val shrinkAndTwist: Triangle => Triangle = val q = 0.05F val p = 1 - q def combine(a: Point, b: Point) = Point(p * a.x + q * b.x, p * a.y + q * b.y) { case Triangle(a,b,c) => Triangle(combine(a,b), combine(b,c), combine(c,a)) } As for the Java code that shrinks and twists a triangle, in our Scala code, we encapsulate it in function shrinkAndTwist. q = 0.05F; p = 1 - q; float … xA, yA, xB, yB, xC, yC, xA1, yA1, xB1, yB1, xC1, yC1, p, q; @philip_schwarz
  • 14. float side = 0.95F * minMaxXY, sideHalf = 0.5F * side, h = sideHalf * (float) Math.sqrt(3), …; int maxX, maxY, minMaxXY, xCenter, yCenter; void initgr() { Dimension d = getSize(); maxX = d.width - 1; maxY = d.height - 1; minMaxXY = Math.min(maxX, maxY); xCenter = maxX / 2; yCenter = maxY / 2; } val panelSize: Dimension = getSize() val panelWidth = panelSize.width - 1 val panelHeight = panelSize.height - 1 val panelCentre = Point(panelWidth / 2, panelHeight / 2) val triangleSide = 0.95F * Math.min(panelWidth, panelHeight) val triangleHeight = (0.5F * triangleSide) * Math.sqrt(3).toFloat val triangle = makeTriangle(panelCentre, triangleSide, triangleHeight) xA = xCenter - sideHalf; yA = yCenter - 0.5F * h; xB = xCenter + sideHalf; yB = yA; xC = xCenter; yC = yCenter + 0.5F * h; As for the Java code that computes the first triangle from the dimensions of the Canvas on which it is going to be drawn, here it is, together with the corresponding Scala code, which draws on a JPanel. object Triangle: def apply(centre: Point, side: Float, height: Float): Triangle = val Point(x,y) = centre val halfSide = 0.5F * side val bottomLeft = Point(x - halfSide, y - 0.5F * height) val bottomRight = Point(x + halfSide, y - 0.5F * height) val top = Point(x, y + 0.5F * height ) Triangle(bottomLeft,bottomRight,top)
  • 15. class Triangles: JFrame.setDefaultLookAndFeelDecorated(true) val frame = new JFrame("Triangles: 50 triangles inside each other") frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE) frame.setSize(600, 400) frame.add(TrianglesPanel()) frame.setVisible(true) @main def main: Unit = // Create a panel on the event dispatching thread SwingUtilities.invokeLater( new Runnable(): def run: Unit = Triangles() ) public class Triangles extends Frame { public static void main(String[] args) { new Triangles(); } Triangles() { super("Triangles: 50 triangles inside each other"); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setSize(600, 400); add("Center", new CvTriangles()); setVisible(true); } } And finally, let’s translate the rest of the code, which creates the application’s frame.
  • 16. Now let’s run the Scala program, to verify that it works OK. @philip_schwarz
  • 17.
  • 18. Now let’s run the program again after temporarily tweaking it so that each side of a triangle is drawn in a different colour.
  • 19.
  • 20. And now let’s repeat that, but with different colours and a black background.
  • 21.
  • 22. The next slide shows our Scala code in its entirety, and the subsequent slide shows the whole of the Java code again, for comparison.
  • 23. class TrianglesPanel extends JPanel: setBackground(Color.white) override def paintComponent(g: Graphics): Unit = super.paintComponent(g) val panelSize: Dimension = getSize() val panelWidth = panelSize.width - 1 val panelHeight = panelSize.height - 1 val panelCentre = Point(panelWidth / 2, panelHeight / 2) val triangleSide: Float = 0.95F * Math.min(panelWidth, panelHeight) val triangleHeight: Float = (0.5F * triangleSide) * Math.sqrt(3).toFloat val shrinkAndTwist: Triangle => Triangle = val q = 0.05F val p = 1 - q def combine(a: Point, b: Point) = Point(p * a.x + q * b.x, p * a.y + q * b.y) { case Triangle(a,b,c) => Triangle(combine(a,b), combine(b,c), combine(c,a)) } def drawLine(a: Point, b: Point): Unit = val (ax,ay) = a.deviceCoords(panelHeight) val (bx,by) = b.deviceCoords(panelHeight) g.drawLine(ax, ay, bx, by) val draw: Triangle => Unit = case Triangle(a, b, c) => drawLine(a, b) drawLine(b, c) drawLine(c, a) val triangle = Triangle(panelCentre, triangleSide, triangleHeight) LazyList.iterate(triangle)(shrinkAndTwist).take(50).foreach(draw) class Triangles: JFrame.setDefaultLookAndFeelDecorated(true) val frame = new JFrame("Triangles: 50 triangles inside each other") frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE) frame.setSize(600, 400) frame.add(TrianglesPanel()) frame.setVisible(true) @main def main: Unit = // Create a panel on the event dispatching thread SwingUtilities.invokeLater( new Runnable(): def run: Unit = Triangles() ) case class Point(x: Float, y: Float) extension (p: Point) def deviceCoords(panelHeight: Int): (Int, Int) = (Math.round(p.x), panelHeight - Math.round(p.y)) object Triangle: def apply(centre: Point, side: Float, height: Float): Triangle = val Point(x,y) = centre val halfSide = 0.5F * side val bottomLeft = Point(x - halfSide, y - 0.5F * height) val bottomRight = Point(x + halfSide, y - 0.5F * height) val top = Point(x, y + 0.5F * height ) Triangle(bottomLeft,bottomRight,top) case class Triangle(a: Point, b: Point, c: Point)
  • 24. public class CvTriangles extends Canvas { int maxX, maxY, minMaxXY, xCenter, yCenter; void initgr() { Dimension d = getSize(); maxX = d.width - 1; maxY = d.height - 1; minMaxXY = Math.min(maxX, maxY); xCenter = maxX / 2; yCenter = maxY / 2; } int iX(float x) { return Math.round(x); } int iY(float y) { return maxY - Math.round(y); } public void paint(Graphics g) { initgr(); float side = 0.95F * minMaxXY, sideHalf = 0.5F * side, h = sideHalf * (float) Math.sqrt(3), xA, yA, xB, yB, xC, yC, xA1, yA1, xB1, yB1, xC1, yC1, p, q; q = 0.05F; p = 1 - q; xA = xCenter - sideHalf; yA = yCenter - 0.5F * h; xB = xCenter + sideHalf; yB = yA; xC = xCenter; yC = yCenter + 0.5F * h; for (int i = 0; i < 50; i++) { g.drawLine(iX(xA), iY(yA), iX(xB), iY(yB)); g.drawLine(iX(xB), iY(yB), iX(xC), iY(yC)); g.drawLine(iX(xC), iY(yC), iX(xA), iY(yA)); xA1 = p * xA + q * xB; yA1 = p * yA + q * yB; xB1 = p * xB + q * xC; yB1 = p * yB + q * yC; xC1 = p * xC + q * xA; yC1 = p * yC + q * yA; xA = xA1; xB = xB1; xC = xC1; yA = yA1; yB = yB1; yC = yC1; } } } // Triangles.java: This program draws 50 // triangles inside each other. public class Triangles extends Frame { public static void main(String[] args) { new Triangles(); } Triangles() { super("Triangles: 50 triangles inside each other"); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setSize(600, 400); add("Center", new CvTriangles()); setVisible(true); } }
  • 25. That’s all for now. See you in Part 2. @philip_schwarz