SlideShare uma empresa Scribd logo
1 de 25
Baixar para ler 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

Mais conteúdo relacionado

Mais procurados

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
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Philip Schwarz
 
Introduction to kotlin and OOP in Kotlin
Introduction to kotlin and OOP in KotlinIntroduction to kotlin and OOP in Kotlin
Introduction to kotlin and OOP in Kotlinvriddhigupta
 
Functions in c++
Functions in c++Functions in c++
Functions in c++Maaz Hasan
 
Module 05 Preprocessor and Macros in C
Module 05 Preprocessor and Macros in CModule 05 Preprocessor and Macros in C
Module 05 Preprocessor and Macros in CTushar B Kute
 
Circular link list.ppt
Circular link list.pptCircular link list.ppt
Circular link list.pptTirthika Bandi
 
Hash table in java
Hash table in javaHash table in java
Hash table in javasiriindian
 
Intermediate code generator
Intermediate code generatorIntermediate code generator
Intermediate code generatorsanchi29
 
Simplifies and normal forms - Theory of Computation
Simplifies and normal forms - Theory of ComputationSimplifies and normal forms - Theory of Computation
Simplifies and normal forms - Theory of ComputationNikhil Pandit
 
Inline function
Inline functionInline function
Inline functionTech_MX
 
Pointers & References in C++
Pointers & References in C++Pointers & References in C++
Pointers & References in C++Ilio Catallo
 
텐서플로로 OCR 개발해보기: 문제점과 문제점과 문제점
텐서플로로 OCR 개발해보기: 문제점과 문제점과 문제점텐서플로로 OCR 개발해보기: 문제점과 문제점과 문제점
텐서플로로 OCR 개발해보기: 문제점과 문제점과 문제점if kakao
 
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Ruslan Shevchenko
 
Introduction to CLIPS Expert System
Introduction to CLIPS Expert SystemIntroduction to CLIPS Expert System
Introduction to CLIPS Expert SystemMotaz Saad
 
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
 

Mais procurados (20)

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...
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
 
Introduction to kotlin and OOP in Kotlin
Introduction to kotlin and OOP in KotlinIntroduction to kotlin and OOP in Kotlin
Introduction to kotlin and OOP in Kotlin
 
Functions in c++
Functions in c++Functions in c++
Functions in c++
 
Module 05 Preprocessor and Macros in C
Module 05 Preprocessor and Macros in CModule 05 Preprocessor and Macros in C
Module 05 Preprocessor and Macros in C
 
Chapter 2 ds
Chapter 2 dsChapter 2 ds
Chapter 2 ds
 
Circular link list.ppt
Circular link list.pptCircular link list.ppt
Circular link list.ppt
 
Hash table in java
Hash table in javaHash table in java
Hash table in java
 
Java programming-examples
Java programming-examplesJava programming-examples
Java programming-examples
 
Intermediate code generator
Intermediate code generatorIntermediate code generator
Intermediate code generator
 
Simplifies and normal forms - Theory of Computation
Simplifies and normal forms - Theory of ComputationSimplifies and normal forms - Theory of Computation
Simplifies and normal forms - Theory of Computation
 
Inline function
Inline functionInline function
Inline function
 
Conversion of Infix To Postfix Expressions
Conversion of Infix To Postfix Expressions Conversion of Infix To Postfix Expressions
Conversion of Infix To Postfix Expressions
 
Pointers & References in C++
Pointers & References in C++Pointers & References in C++
Pointers & References in C++
 
텐서플로로 OCR 개발해보기: 문제점과 문제점과 문제점
텐서플로로 OCR 개발해보기: 문제점과 문제점과 문제점텐서플로로 OCR 개발해보기: 문제점과 문제점과 문제점
텐서플로로 OCR 개발해보기: 문제점과 문제점과 문제점
 
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
 
Compiler Design- Machine Independent Optimizations
Compiler Design- Machine Independent OptimizationsCompiler Design- Machine Independent Optimizations
Compiler Design- Machine Independent Optimizations
 
Introduction to CLIPS Expert System
Introduction to CLIPS Expert SystemIntroduction to CLIPS Expert System
Introduction to CLIPS Expert System
 
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...
 
C Structures & Unions
C Structures & UnionsC Structures & Unions
C Structures & Unions
 

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

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

Mais de Philip Schwarz

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip 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
 
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
 
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
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...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
 
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
 

Mais de Philip Schwarz (20)

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
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
 
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
 
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...
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
 
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...
 
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
 

Último

Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptrcbcrtm
 

Último (20)

Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.ppt
 

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