Вы находитесь на странице: 1из 76

Computational Analysis with

Scientific Computing -
with sample code and
explanation
Part I

authored by:
Sifiso Samson “BlackCid” Thwala
Preface
IT is a vast field that overwhelms me and my fellow acquaintances hence we are actually studying,
researching and trying our level best to develop IT as much as possible. IT ranges from (fundamentally)
bitwise operations used in machine level to number manipulation used in computational applications to
combinatorial problems leading to the ever so vast study of AI (Artificial intelligence) to matrix calculus
which is the basis of graphics and graphical user interfaced applications, etc... Scientific computing -
which was highly used in this portfolio and most, if not all, of my projects – is a collection of tools,
techniques and theories required to develop and solve mathematical models in science and engineering on a
computer, bridging the gap of the theoretical side of academics and the work experience of professionals to
produce a well thought after solution to common and even critically rare and unconsidered problems.

It as been my life’s work to ponder ideas and research in this industry, so I hope the few examples I have
compiled here for illustration purposes offer more insight on IT itself than praise any persona, for the
discipline itself is the future and let man give his all to it, in order of it to grow.

The basis of the code provided will be written in this documentation, for background knowledge into the
problems solved in the dot CPP of dot JAVA files accompanying thin document. All implementations and
testing of the C++ programs have been done of gcc 3.3, DevC++ and Microsoft Visual Studio.NET, while
for java I used version 1.6.0 (jdk1.6.0), May you not have any problems running the executable file given.
Should you need to recompile, you may, provided that the original file are not modified directly.

Acknowledgement:
Most of the code and research topics, are inspired or preview of the of the work of the following Doctor
and Professors, visit their site to view their phenomenal work. Official Website: http://issc.rau.ac.za

Prof. Willi-Hans Steeb


Steeb_wh@yahoo.com
Dr. Yorick Hardy
yorickhardy@yahoo.com
yha@na.rau.ac.za
Prof. Alexandre Hardy
ah@a.rau.ac.za
(Yes their related, in-fact they’re twins)
Dr. Ruedi Stoop
ruedi@ini.phys.ethz.ch

Author’s email address: Thwala.mansion@gmail.com


All dependencies and additional file are found on my website under the publication bias menu

© All rights are reserved by the University of Johannesburg, meaning that this documentation and/or the underlying
code may not be reproduced in any form or by any means, electronic or mechanical, including photocopying,
recording or any information storage and retrieval system now known or to be inverted, without written permission
from the author
Contents

Security
Checksum
Cyclic Redundancy Checks
Functionality
Exclusive OR function
Baeza-Yates-Gonnet
Let’s play
The Maze
Sudoku
Practical
Finite State Machines
Dictionary Word Processor
ChatRoom
Mathematics
Eigenvalues and Eigenvectors
Matrix class in C#
Graphics
Grey Picture
GIMP
Bézier curve
Harmonic interpolation

Bibliography
Checksum
checksum.cpp

A checksum can be used to determine if errors occurred in transmission of data. It is widely used in the
internet by several protocols. The checksum works as a liner and cyclic code does yet it is based on the
concept of redundancy, several protocols within the internet model still primarily use it for error detect.
The checksum is based on a 32-bit checksum algorithm that simply adds all data in the transmission as if it
were 32-bit quantities, i.e. we read 4 bytes each and the resulting 32-but quantities, when the checksum
overflows, and the overflow bit is added to the checksum.

i) Find the checksum for ABCD

For the String ABCD we have: 65 + 66*256+66*256 2 +68*256 3 = 11455258561


Where the used the ASCII table, in which ‘A’ => 65 , ‘B’ => 66, ‘C‘ => 67 and ‘D’ => 68

ii) The underlying Checksum.cpp code will illustrate: Checksum computation of some data and
provide options for comparing the checksum to a given value.

/* */
/* checksum.cpp */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

#include <fstream>
#include <iostream>
using namespace std;

unsigned int checksum(istream &in)


{
unsigned int sum = 0;
unsigned int value;
while(!(in.eof()))
{
value = 0; //for padding - empty padding
in.read((char*)& value,sizeof(unsigned int));
if(!in.eof())
{
if( sum + value < sum )
{// that means its an over flow!
sum += value;
sum++;
}
else
{
sum += value;
}
}
}
return sum;
}

int main(int argc, char *argv[])


{
ifstream file;
if(argc < 2)
{
cout << "std in : " << checksum(cin) << endl;
}
else
{
for(int i = 1; i < argc; i++)
{
file.open(argv[i],ios::in | ios::binary);
cout << argv[i] << " : " << checksum(file) << endl;
file.clear();// Remember to close streams this is C++!
file.close();
}
}
cout << "Success, now executable is closing." << endl;
system("pause");
return 0;
}

iii) Pitfall: If we look at the checksum it is clear that any difference in two sequences of 32-bit
values that is not a multiple of 2 32 in total will result in a different checksum. This allows us
to detect all errors that do not produce a difference in the sum of precisely 2 32 =
4294967296. The checksum in this example is further improved by the addition of the carry
bit. The addition of the carry bit will prevent multiples of 4294967296 from being detected as
a no error condition. So now all errors must result in a net increase of zero in the sum if they
are to go undetected, i.e., some values must decrease and others increase to get a net result of
zero difference over the sum.
Cyclic
Redundancy
Checks
CRC32.cpp

Cyclic redundancy checks provide a better means of checking data for errors (well it’s the closest one
before to brute force).Cyclic Codes are special linear block codes with one extra property, in cyclic code, if
a code word is cyclically shifted (rotated), the result is another code word and the a Cyclic redundancy
check is an instance of cyclic code.

The cyclic redundancy 32 polynomial

G ( x) = x 32 + x 26 + x 23 + x 22 + x16 + x12 + x11 + x8 + x 7 + x 5 + x 4 + x 2 + x + 1


is a commonly used polynomial for error detection. This polynomial is resented as a bit string where each
coefficient (1 or 0) is a binary digit in the string. To check for errors in transmitted data we do the
following:
iv) compute the CRC of the to be sent
v) send the data and the CRC
vi) Recompile the CRC and check whether it matches the sent CRC
To compute the CRC we do the following: we let B(x) be the data to be sent plus 32 0’s appended(i.e.,
multiply by x 32 ). Now we calculate R(x) = B(x) mod G(x), and set T(x) = B(x) – R(x). This sets the low
bits of T to R. We transmit T to get T’. If T’(x) mod G(x) = 0 then there was no error. We can perform the
remainder calculation a feedback shift register:
• Create a register with 32 bits, all set to zero
• For each G(x) where the coefficient is 1, build an XOR gate so the output is ‘xoorred’ – Allow me
coil that word – with the bit that is shifted into that register.
The data bits are shifted in one at time all the bits shift one position on, and if there is an XOR gate then
XOR the position with the value in the last register. The solutions to questions passed in this discussion are
answer in the cpp file named CRC32.cpp

/* */
/* CRC32.cpp */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */
#include <iostream>
#include <bitset>
#include <iomanip>
#include <fstream>

using namespace std;

int poly[]={ 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26, -1 };


const unsigned long n = 32;
bitset<n> result;
bitset<n> crc32(bitset<8> data)
{
bool bit;
int xorpos, pos;

for( int i = 0; i < 8; i++)


{

bit = result[31];
result <<= 1;
result.set(0,data[i]);
xorpos = 0;
while( poly[xorpos] != -1 )
{
pos = poly[xorpos];
result.set(pos,bit^result[pos]);
xorpos++;
}
}
return result;
}

void calc_crc( istream& in)


{
unsigned char c;
bitset<n> crc;
result.reset();
while(!in.eof())
{
in.read( (char*) &c, 1 );
if( !in.eof() )
{
bitset<8> data(c);
crc = crc32(data);
}
}
cout << crc << "(" << setbase(16) << crc.to_ulong() << ")" << endl;
}
int main(int argc, char *argv[])
{
ifstream fin;
if(argc > 1)
{
for(int i = 1; i <argc ; i++)
{
fin.open(argv[i],ios::in|ios::binary);
cout << argv[i] << " : ";
calc_crc(fin);
fin.close();
}
}else { calc_crc(cin); }
return 0;
}
Exclusive OR function
XOR
XOR.java

Now the origins of this function dates far back from the evolutions of logic from mathematics and has been
a tool ever since. Although the precise date of the XOR function’s origins is undetermined, the modern use
of it fascinated me because it’s an essential tool to modern Structures such as Graphics.

In the Graphics class of Java the method:

public abstract void setVORMode( Color c1)

sets the paint mode of this Graphics context to alternate between this Graphics context’s current colour and
the new specified colour.

The big question is how?


This specifies that the logical pixel operations are performed in the XOR mode, which alternate pixels
between the current colour and a specified XOR colour. When drawing operations are performed, pixels
which are the current colour are changed to the specified colour, and vice versa.
In other words, we XOR the colour c of the pixel being written with current ⊕ c1, i.e.,

current = (current ⊕ c1) ⊕ c1,


c1 = (current ⊕ c1) ⊕ current

The java illustration shows this…

/* */
/* CXOR.java */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class XOR extends Applet


{
private Color strawberry = new Color(0xcc,0,0x66);
private Color chocolate = new Color(0x66,0x33,0);
private Color vanilla = new Color(0xff,0xff,0x99);
private Color scoop = new Color(0x33,0x99,0xcc);
private static final int BORDER = 10;

public void init()


{
setBackground(chocolate);

addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
Graphics g = getGraphics();
g.setColor(chocolate);
g.setXORMode(scoop);
Dimension dim = getSize();
int diameter = dim.height - (2*BORDER);
int xStart = (dim.width/2) - (diameter/2);
int yStart = BORDER;
g.fillOval( xStart, yStart, diameter, diameter);
g.setPaintMode();
}
}
);
}

public void paint(Graphics g)


{
Dimension dim = getSize();
int width = dim.width/3;
int height = dim.height;
g.setColor(strawberry);
g.fillRect(0,0,width,height);
g.setColor(vanilla);
g.fillRect(dim.width - width,0,width,height);
}
public static void main()
{
XOR ap = new XOR();
ap.init();
ap.show();
}
}

The accompanying Applet was written on html and compled with version: 1.6.0_16 of the java runtime.

<!-- generated edited and modified


<!-- Sifiso "BlackCid" Thwala -->
<!-- http://www.BlackCid.co.za -->
<!-- -->

<html>
<head><title>practice</title></head>
<body>
<applet code="XOR.class" width="400" height="400" align="centre" >
</applet>
</body>
</html>
Baeza-Yates-Gonnet
Algorithm
Byg.cpp
The Baeza-Yates-Gonnet algorithm (BYG algorithm,) for searching for a pattern in a string runs 40-50 per-
cent faster than KMP.
The technique works as follows:
• Build a table of bitmasks for each letter of the alphabet, the mask has the length of the search pat-
tern. Each bit is 1 (if that letter is not in that position).
• Create a working bitmask, initialized to all1’s.
• For each letter in the search string, shift the working mask 1 bit to the left and perform the logical
or with the bitmask for the letter in that position of the string.
• Let the length of the search pattern be x. If the bit in position x of the working bitmask is 0, then
the String matches.
• If we reach the end of the string without finding a match, then there is no match.

The c++ program to match strings using the BYG algorithm

/* */
/* byg.cpp */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

#include <iostream>
#include <string>
#include <bitset>
using namespace std;

const int MASKSIZE = 32;


bitset<MASKSIZE> masks[256];
string pattern;

void prepare_masks(string s)
{
for(int i = 0; i < 256; i++)
{
masks[i].reset();
for(int j = 0; j < s.length(); j++)
if(( (unsigned char)s[j] ) ==i ) masks[i].set(j);
masks[i].flip();
}
pattern = s;
}

int match(string s)
{
int i = 0;
while( i < s.length() )
{
bitset<MASKSIZE> work;
work.flip();
while ( i < s.length() )
{
work <<= 1;
work|masks[(unsigned char)s[i]];
if(!(work.test(pattern.length()-1)))
{ return i+1-pattern.length(); }
i++;
}
}
return -1;
}

int main(void)
{
string needle, haystack;
int pos;
cout<<"Enter String to search in : ";
getline(cin,haystack);
cout<<"Enter search string : ";cin >> needle;
prepare_masks(needle);
if((pos = match(haystack))>0)
cout<<"Match found at "<< pos << " starting at 0" << endl;
else
cout<<"No match" << endl;
system("pause");
return 0;
}
The Maze
Maze.java

The maze is an illustration of recursion; a blood hound implementation is given here which find the
possible solution to the maze a maze which could be randomly generated but for illustration purses hard
coding will do the trick. The aim of the maze is to move from position (0, 0) – top left corner – to the
position (m – 1, n – 1) – bottom right corner following the path’s of 1’s. We can only move to the right,
left, down and up but not diagonal. Write a java program using recursion that find out whether or not
there’s a solution and if so provide a solution which is denoted as a path of 5’s.

This common recursive problem that occurs in many disciplines but the most exciting one is within infinite
state machine especially severs and other none terminating applications and machinery.

/* */
/* Maze.java */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

public class Maze


{
public static int[][]A ={ {1, 1, 1, 0, 0, 0, 1, 0,},
{0, 1, 1, 0, 1, 1, 1, 0,},
{0, 0, 1, 1, 0, 1, 0, 0,},
{1, 1, 0, 1, 1, 1, 1, 0,},
{0, 1, 1, 0, 0, 0, 1, 1,},
{1, 1, 0, 1, 1, 0, 1, 1,},
{1, 0, 1, 0, 1, 0, 1, 0,},
{1, 0, 0, 1, 0, 0, 1, 1,}};

public static void display()


{
for(int r = 0; r < A.length; r++)
{
for(int c = 0; c < A[r].length; c++)
System.out.print(A[r][c]);
System.out.println();
}
System.out.println();
}
public static boolean solve( int r, int c)
{
boolean done = false;
if(valid(r,c) != false)
{
A[r][c] = 3; //cell has been tried
if( (r == A.length -1) && (c == A[0].length-1) )
done = true;// maze is solved
else
{
done = solve(r+1,c); // down
if( done == false ) done = solve(r,c+1); // right
if( done == false ) done = solve(r-1,c); //up
if( done == false ) done = solve(r,c-1); // left
}
if( done != false ) A[r][c] = 5;
}
return done;
}

public static boolean valid(int r ,int c)


{
boolean result = false;
if( (r >= 0) && (r < A.length) && (c >= 0) && (c < A[0].length) )
if(A[r][c] == 1) result = true;
return result;
}

public static void main(String[] args)


{
Maze lab = new Maze();
lab.display();
if(lab.solve(0,0) != false)
System.out.println("Maze solved");
else System.out.println("no solution");
lab.display();
}
}
Sudoku
Sudoku.cpp

Sudoku is a numerical puzzle. The puzzle consists of 9x9 squares arranged in a grid. This grid is further
subdivided into 3x3 squares of size 3x3. Some numbers are initially placed on the grid. To solve the puzzle,
a number between 1 and 9 (inclusive) must be selected for each square that is empty so that:
1. No number is duplicated in any row.
2. No number is duplicated in any column.
3. No number is duplicated in any of the 3x3 subgrids.
This a program allows a user to specify and solve a sudoku puzzle. Initially the 9x9 grid is empty, the user
types in the numbers that are given for the puzzle. Thereafter, the user types in the numbers that he/she has
computed to solve the puzzle at each stage.
The program displays the puzzle on the screen, with the entered numbers after each new number is entered.
Note: The user can choose to enter a new number at any position he/she chooses, as long as there is
no number there already.
After all squares have been filled with a number, I check that the puzzle has a solution by making sure that
the above constraints are satisfied. Note: there may be many, or perhaps no solutions to the puzzle.

/* */
/* Sudoku .cpp */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int grid[9][9];

void playGame();
bool placeValues = true;

//Clears all values in the grid to 'empty'


void clearGrid()
{
int i,j;

for (i=0;i<9;i++)
{
for (j=0;j<9;j++)
{
grid[i][j] = 0;
}
}
}

//Scans a row to detect duplicate values


bool isNumInRow(int num, int row, int exclude)
{
int x;
for (x=0;x<9;x++)
{
if (x!=exclude)
{
if (grid[x][row]==num)
return true;
}
}
return false;
}

//Specify the x, y coodinates of the subboard that you are working with
bool isSubBoardSafe(int x, int y)
{
int i, j;

//Use a static array to represent all posible values (1-9)


//For each value that exists in the subboard, its value is set = true
//If an element in array is being set = true twice, there are duplicates in the subboard
bool nums[9];
for (i=0;i<9;i++)
nums[i]=0;
for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
if (grid[i+x][j+y]!=0)
{
if (nums[grid[i+x][j+y]-1]==false)
nums[grid[i+x][j+y]-1]=true;
else
return false;
}
}
}
return true;
}

//Detect if any duplicates exist within each of the subboards


bool areSubBoardsSafe()
{
if (isSubBoardSafe(0,0)==false)
return false;
if (isSubBoardSafe(0,3)==false)
return false;
if (isSubBoardSafe(0,6)==false)
return false;

if (isSubBoardSafe(3,0)==false)
return false;
if (isSubBoardSafe(3,3)==false)
return false;
if (isSubBoardSafe(3,6)==false)
return false;

if (isSubBoardSafe(6,0)==false)
return false;
if (isSubBoardSafe(6,3)==false)
return false;
if (isSubBoardSafe(6,6)==false)
return false;

return true;
}

//Scans a column to detect duplicate values


bool isNumInCol(int num, int col, int exclude)
{
int y;
for (y=0;y<9;y++)
{
if (y!=exclude)
{
if (grid[col][y]==num)
return true;
}
}
return false;
}

//Scans all rows and columns to detect duplicates


bool anyDuplicates()
{
int i,j;
for (i=0;i<9;i++)
{
for (j=0;j<9;j++)
{
if (grid[i][j]!=0)
{
//i = col
//j = row
if ( isNumInCol(grid[i][j], i, j) )
return true;
if (isNumInRow(grid[i][j], j, i))
return true;
}
}
}
return false;
}

//Checks to make sure that all elements in the grid have been allocated a value
bool isGridFull()
{
int i,j;
for (i=0;i<9;i++)
{
for (j=0;j<9;j++)
{
if (grid[i][j]==0)
return false;
}
}
return true;
}

//Returns a string value to represent a grid position


string getChar(int num)
{
if (num==0)
return " ";

//Converts an integer to a string


stringstream ss;
ss << num;

//Return the new string


return ss.str();
}

//Place a piece (0-8, 0-8)


bool placePiece(int x, int y, int val)
{
if ((x<0)or(x>9)or(y<0)or(y>9)or(val<0)or(val>9))
{
cout << "A value is out of bounds!" << endl;
return false;
}
if (grid[x][y]!=0)
{
cout << "A value already exists at this position!" << endl;
return false;
}
grid[x][y]=val;
return true;
}

//Displays the game grid on the screen


void drawGrid()
{
system("cls");
if (placeValues==true)
cout << " <<Please Specify The Sudoku Puzzle>>" << endl;
else
cout << " SUDOKU" << endl;

int i,j;
cout << endl;
cout << " =====================================" << endl;
for (i=0;i<9;i++)
{
for (j=0;j<9;j++)
{
if ((j)%3==0)
cout << " I " << getChar(grid[j][i]);
else
cout << " : " << getChar(grid[j][i]);
}
if ((i+1)%3==0)
cout << " I" << endl << " =====================================";
else
cout << " I" << endl << " -------------------------------------";
cout << endl;
}
cout << endl;
}
//Asks the user for input, to populate the game grid with values
void askPos()
{
int s, r, c;
int val;

cout << "What subgrid would you like work with (1-9)?" << endl;
if (placeValues==true)
cout << " [0 to stop setting up game]" << endl << endl;
else
cout << " [0 to quit, -1 to restart]" << endl << endl;
cout << " 1|2|3" << endl;
cout << " -----" << endl;
cout << " 4|5|6" << endl;
cout << " -----" << endl;
cout << " 7|8|9 = ";
cin >> s;

if (s==0)
{
if (placeValues==true)
{
placeValues = false;
system("cls");
cout << endl << "You have successfully set up the game grid!" << endl << "Good luck with your
puzzle!" << endl;
system("pause");
return;
}
else
exit(0);
}
if (s==-1)
{
placeValues=true;
clearGrid();
playGame();
}
cout << endl << "What row within this subgrid?" << endl;
cin >> r;
cout << "What column within this subgrid?" << endl;
cin >> c;
cout << "What number would you like to place at this position (1-9)?" << endl;
cin >> val;

//Failure detection for input


if (cin.fail())
{
cin.clear();
string dummy;
cin >> dummy;
}

//Reposition row and column based on which subgrid we are working with
r = (((s-1)/3)*3)+ r-1;
c = (((s-1)%3)*3)+ c-1;

if ((r<0)||(c<0)||(r>8)||(c>8))
r=-1;

cout << endl;


//Invalid subgrid
if (r==-1)
{
cout << "Sorry, invalid subgrid number!" << endl;
system("pause");
}
else if (placePiece(c,r,val)==false)
{
cout << "Sorry, your move could not be made!" << endl;
system("pause");
}
else
drawGrid();

}
//Detect if the game is over, and the user has won
bool isGameOver()
{
if (isGridFull())
{
if (anyDuplicates()==false)
{
if (areSubBoardsSafe()==true)
return true;
}
}
return false;
}

//Main method to ask the user for a value, redraw the game grid, then check for a win condition
void playGame()
{
drawGrid();
askPos();

if (isGameOver())
{
drawGrid();
cout << endl;
cout << " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" << endl;
cout << " Congratulations, you have successfully completed the Sudoku puzzle!" << endl;
cout << " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" << endl;
cout << endl;
system("pause");
return;
}
else if (isGridFull()) //Game does not satify win conditions, but no positions are open: user has lost
{
drawGrid();
cout << endl;
cout << " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" << endl;
cout << " Sorry, you have failed to complete the Sudoku puzzle correctly!" << endl;
cout << " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" << endl;
cout << endl;
system("pause");
return;
}
playGame();
}

int main()
{
clearGrid();
playGame();
return 0;
}
Finite
State
Machines
machine.cpp

This is a skeleton design of a Mealy machine to represent a vending machine which provides a carbonated
drink for R2,50. The machine accepts 50c, R1 and R2 coins. The symbol number output by the machine is
interpreted a change (in cents) for the customer. The symbol ‘c’ output by the machine is interpreted as the
output of the carbonated drink. We allow null output, i.e., output which does not actually appears (empty
string). Thus the output ‘symbols’ we could expect are the strings:

Output is: “”,”C”,”C50”, “C100”, “C150”.

For the illustration I use the states to indicate how many 50c the vending machine has received. In other
words S0 represents 0c, S50 represents 50c and so on. The following transition table describes the machine.

State Input Output Next State


S0- 50c S50
S0- R1 S100
S0- R2 S200

S50 50c S100


S50 R1 S150
S50 R2 C S0

S100 50c S150


S100 R1 S200
S100 R2 C50 S0

S150 50c S200


S150 R1 C S0
S150 R2 C100 S0

S200 50c C S0
S200 R1 C50 S0
S200 R2 C150 S0
/* Machine.java */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */
import java.io.*;
public class Machine
{
static transition trans[] =
{ new transition("S0","50c","","S50"),
new transition("S0","R1","","S100"),
new transition("S0","R2","C","S200"),
new transition("S50","50c","","S100"),
new transition("S50","R1","","S150"),
new transition("S50","R2","C","S0"),
new transition("S100","50c","","S150"),
new transition("S100","R1","","S200"),
new transition("S100","R2","C50","S150"),
new transition("S150","50c","","S200"),
new transition("S150","R1","C","S0"),
new transition("S150","R2","C100","S0"),
new transition("S200","50c","c","S0"),
new transition("S200","R1","C50","S0"),
new transition("S200","R2","C150","S0"),
new transition(null,null,null,null)
};
static String output[][] =
{ { "" , "" },
{"C","Machine produces a can\n"},
{"C50","Machine produces a can and 50 cnts change\n"},
{"C100","Machine produces a can and R1 change\n"},
{"C150","Machine produces a can and R1.50 change\n"},
{null,null}
};
public static void main(String[] args) throws IOException
{
String state = trans[0].state;
String input = "";
int i = 0, j =0;
BufferedReader kbd = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Input a 50c, R1 or R2 coin");
input = kbd.readLine();
for( i = 0; i < trans.length; )
{
if(!((state.equals(trans[i].state)) && (input.equals(trans[i].input))))
{i++;}
else
{
for( j = 0; output[j][0] != null; j++)
if((trans[i].output).equals(output[j][0]))
System.out.println( output[j][1] );
state = trans[i].nextstate;
}
i = 0;
System.out.println("Input a 50c, R1 or R2 coin");
}
}
}
class transition
{
String state, input, output, nextstate;
public transition(String st, String in, String out, String ne)
{
state = st;
input = in;
output = out;
nextstate = ne;
}
}
Dictionary Word Processor
SpellChecker.cpp

The program is a spellchecker program. The program takes parameters on the command line to specify the
file to be checked and optionally the dictionary file. The dictionary file is read in and stored in memory.
The program reads the file to be spellchecked word for word, and sees if each word is in the dictionary file.
If the file has a spelling error an option to change the word (in which case the file is modified). The modi-
fied file is written to a new file.

The program adheres to the following requirements:

• You must use a binary search algorithm to check if the word is in the dictionary.
• Make suggestions when a spelling mistake has been made.
• Ignore the case of words. (Hint: use to upper)
• Ignore punctuation.

The dictionary is made available as words.txt in the same folder.

The spell checker Challenge is a special case that is continuously and new commonly used way of alternat-
ive words. Instead of lexicon order of the alphabet it also detects meaning, so it detects a couple of letters
of cases. Like ‘impottant’ would be important

Note the words to be searched and the dictionary(words to be compared to) may be found on my site.

/* */
/* Sudoku .cpp */
/* original authors: */
/* Sifiso "BlackCid" Thwala */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* Note!! The dictionary file may be downloaded from my site as: words.dict */

#include <cctype>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>

using namespace std;

vector <string> dict;


int nearindex;

//Return the index of the word


//If word isn't found, returns -1
int BinarySearch(string word, int low, int high)
{
int mid = (low+high)/2;
if (low>high)
return mid; //Word wasnt found, nearest index is returned
if (word==dict[mid])
return -1; // -1 means that the word was found
else if(word < dict[mid])
return BinarySearch(word, low, mid-1);
else
return BinarySearch(word, mid + 1, high);
}

//Returns a vector containing suggestions


void getSuggestions(vector<string> &v, string word)
{
if (word.size()<=1)
return;
int i;
int j;
string temp;
//Remove every letter
for (i=1;i<=word.size();i++)
{
temp = word.substr(0,i-1) + word.substr(i,word.size()-i);
if (BinarySearch(temp,0,dict.size()-1)==-1)
v.push_back(temp);
}
//Add a letter
for (i=0;i<=word.size();i++)
{
for (int j=97;j<=122;j++)
{
temp = word.substr(0,i) + (char)j + word.substr(i,word.size()-i);
if (BinarySearch(temp,0,dict.size()-1)==-1)
v.push_back(temp);
}
}
//replace every letter with another letter...
for (i=1;i<=word.size();i++)
{
for (int j=97;j<=122;j++)
{
temp = word.substr(0,i-1) + (char)j + word.substr(i,word.size()-i);
if (BinarySearch(temp,0,dict.size()-1)==-1)
v.push_back(temp);
}
}
//Swap every letter
for (i=0;i<word.size()-1;i++)
{
temp = word.substr(0,i) + word.substr(i+1,1) + word.substr(i,1) + word.substr(i+2,word.size()-i-2);
if (BinarySearch(temp,0,dict.size()-1)==-1)
v.push_back(temp);
}
}

void LoadDictionary(fstream &File)


{
dict.clear();
string temp;
while (!File.eof())
{
getline(File, temp);
dict.push_back(temp);
}
if (temp=="")
dict.pop_back(); //If last word was blank, remove it
}
bool isLetter(char c)
{
if (((int)c>=97)&&((int)c<=122))
return true;
if (((int)c>=65)&&((int)c<=90))
return true;
return false;
}
//Convert an entire word to lower case
string LowerCase(string word)
{
int j;
for (j=0;j<word.size();j++)
word[j] = (char)tolower(word[j]);
return word;
}

string ReplaceIfNeeded(string word)


{
int index;
int i;
string newword;
index = BinarySearch(LowerCase(word), 0, dict.size()-1);
if (index!=-1)
{
system("cls");
vector<string> slist;
slist.clear();
getSuggestions(slist,LowerCase(word));
if (slist.size()==0)
cout << "'" << word << "' was not found in the dictionary!" << endl << "No suggestions were
found!" << endl;
else
cout << "'" << word << "' was not found in the dictionary!" << endl << "Here are a few
suggestions:" << endl;
for(i=0;i<slist.size();i++)
cout << " -" <<slist[i] << endl;
cout << "Please type in the correct word" << endl;
cin >> newword;
return newword;
}
else
return word;
}

void SpellCheck(fstream &File)


{
string line;
string nextword;
int i;
int st;
fstream fout; //File to save new document
fout.open("checked.txt", ios::out);

while (!File.eof())
{
st=0;
getline(File,line); //Read the current line
for (i=0;i<=line.size();i++) //Iterate throught the line to find each word
{
if ((isLetter(line[i])==false)||(i==line.size()))
{
if (st==i)
{
fout << line[i];
st++;
}
else
{
nextword = line.substr(st,i-st); //Isolates each word in the line
nextword = ReplaceIfNeeded(nextword);
st=i+1;
fout << nextword;
fout << line[i];
}
}
}
fout << "\n";
}
fout.close();
}

int main(int argc, char *argv[])


{
if (argc!=3)
{
cout << "Not enough parameters for program to run!"<< endl;
system("PAUSE");
return 1;
}

fstream dictionary;
fstream fread;
dictionary.open(argv[1], ios::in); //Dictionary
fread.open(argv[2], ios::in); //File to spell check

LoadDictionary(dictionary);
SpellCheck(fread);

system("PAUSE");
dictionary.close();
fread.close();
return 0;
}
ChatRoom
ChatClient.java
ChatRoomServer.java
etc
This program implement a basic electronic chatroom application that employs a multi threaded server.
Client:
The client is implemented as a GUI that can send and receive messages until it sends the string 'Bye'.
A separate thread receives messages from the server and adds them cumulatively to a text area. The thread:
• Accept the user's chatroom nickname via an input dialogue box
• Send this name to the server.
• All other messages are sent via a text area with an associated button.
As a simplification, it is assumed that no two clients will use the same nickname
Server:
The chat server is multi threaded and must be able to:
• Broadcasts each message it receives to all the connected clients.
• Maintain a dynamic list of Socket references associated with those clients. Though you could use
an array to hold the list, the use of a Vector object would be much more realistic.

To get the generated classes and working example visit my site: http://www.BlackCid.co.za
If you find any errors just check the version of you jre, I used version 1.6.0_16.
To run this code run the sever first and then multiple clients after.

/* */
/* ChatRoomServer.java */
/* Created by: */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za*/
/* */

import java.net.*;
import java.io.*;
import java.util.*;

public class ChatRoomServer


{
public static void main(String[] args) throws IOException {
ServerSocket ChatRoomService = null;
boolean listening = true;

try
{
ChatRoomService = new ServerSocket(1234);
}catch(IOException ser)
{
System.err.println("Could not listen on port 1234! ...");
System.exit(-1);
}

System.out.println("Server online!");
System.out.println("Waiting for ChatRoomClients to connect...");
ChatRoomProtocol chatText = new ChatRoomProtocol();
while (listening)
{
new ChatRoomServerThread(ChatRoomService.accept(),chatText).start();
}

ChatRoomService.close();
}
}

/* */
/* ChatClient.java */
/* original authors: */
/* Dr. M Coetzee */
/* marijkec@uj.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za*/
/* */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.net.*;

public class ChatClient extends JFrame implements ActionListener


{
private static Socket socket;
private static Scanner networkInput;
private static PrintWriter networkOutput;
private static ChatClient frame;
private JTextArea chatArea;
private JTextArea messageArea;
private JButton sendButton;
private ChatThread chatThread;
private String message = "";
public static void main(String[] args)

{
connectToChatroom();
frame = new ChatClient();
frame.setTitle("A Simple Chat Client");
frame.setSize(400,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}

public static void connectToChatroom()


{
InetAddress host = null;
final int PORT = 1234;

try
{
host = InetAddress.getLocalHost();
}
catch(UnknownHostException uhEx)
{
System.out.println("\nHost ID not found!\n");
System.exit(1);
}

try
{
socket = new Socket(host,PORT);
networkInput = new Scanner(socket.getInputStream());
networkOutput = new PrintWriter(socket.getOutputStream(),true);
}
catch(IOException ioEx)
{
ioEx.printStackTrace();
System.exit(1);
}

public ChatClient()
{
chatArea = new JTextArea(20,50);
chatArea.setWrapStyleWord(true);
chatArea.setLineWrap(true);
chatArea.setEditable(false);
add(new JScrollPane(chatArea),BorderLayout.CENTER);
JPanel sendPanel = new JPanel();
sendPanel.setLayout(new BorderLayout());
JLabel prompt = new JLabel("Enter message: ");
messageArea = new JTextArea(5,50);
messageArea.setWrapStyleWord(true);
messageArea.setLineWrap(true);
sendButton = new JButton("Send");
sendButton.addActionListener(this);
sendPanel.add(prompt, BorderLayout.WEST);
sendPanel.add(messageArea, BorderLayout.CENTER);
sendPanel.add(sendButton, BorderLayout.EAST);
add(sendPanel, BorderLayout.SOUTH);

chatThread = new ChatThread();

chatThread.start();
//Above thread will 'listen' for incoming chat
//and will display it on the central text area.
}

public void actionPerformed(ActionEvent event)


{
if (event.getSource() == sendButton)
{
message = messageArea.getText();
networkOutput.println(message);
messageArea.setText(""); //Clear area.

if (message.equals("Bye"))
{

try
{
System.out.println("\nClosing connection...");
socket.close();
socket = null;
System.exit(0);
}
catch(IOException ioEx)
{
System.out.println("Unable to disconnect!");
System.exit(1);
}
}
}
}
class ChatThread extends Thread
{
public void run()
{
String handle = JOptionPane.showInputDialog(frame,"Enter your nickname: ",
"Name entry",
JOptionPane.PLAIN_MESSAGE);
String receipt;
networkOutput.println(handle);

do
{

try
{
receipt = networkInput.nextLine();
chatArea.append(receipt + "\n");
}
catch (NoSuchElementException nseEx)
{
//Do nothing. Client has just left chatroom.
}
}while (true);

}
}
}

/* */
/* ChatRoomServerThread.java */
/* Created by: */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za*/
/* */
import java.net.*;
import java.io.*;
import java.util.*;
public class ChatRoomServerThread extends Thread
{
private Socket chatSession = null;
private ChatRoomProtocol chat;

public ChatRoomServerThread(Socket socket,ChatRoomProtocol chatin)


{
super("ChatRoomServerThread");
this.chatSession = socket;
chat = chatin;
chat.populate(socket);
}

public void run()


{
try
{
PrintWriter out = new PrintWriter(chatSession.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
chatSession .getInputStream()));
String per = in.readLine();
chat.inPeeps(per);
Vector display = chat.newEntry();
for(int i =0 ; i< display.size() ; i++)
out.println( (String)display.get(i) );
chat.chats(" I online",per);
String a;
while( (a = in.readLine()) != null )
{
if( a.equals("Bye") )
{
chat.chats(" Bye Im disconnecting ....",per);
return;
}
chat.chats(a,per);
}

chat.delete(chatSession);

out.close();
in.close();
chatSession.close();
} catch (IOException e) {
System.err.println("Accept failed.");
e.printStackTrace();
System.exit(1);
}
}
}

/* */
/* ChatRoomProtocol.java */
/* Created by: */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

import java.lang.*;
import java.lang.String;
import java.net.*;
import java.util.*;
import java.io.*;

public class ChatRoomProtocol


{
private Vector chat = new Vector();
private Vector scribles = new Vector();
private Vector connectedPeeps = new Vector();
private boolean wriiten = false;

public void chats(String ex,String persona)


{
if( chat.size() > 20 )
{
chat.removeElement( (String)chat.get(0) );
}
chat.addElement(persona+" : "+ex);

if( scribles.size() != 1 )
for(int i = 0 ; i < scribles.size() ; i++ )
this.broadCast( (Socket)scribles.get(i) );
else this.broadCast( (Socket)scribles.get(0) );
}

public void broadCast(Socket chatMates)


{
try
{
PrintWriter out = new PrintWriter(chatMates.getOutputStream(), true);
out.println(chat.get( chat.size()-1 ));
}catch (IOException e)
{
e.printStackTrace();
}
}
public void populate(Socket persona)
{
scribles.addElement(persona);
System.out.println("SAved");
}
public void delete(Socket persona)
{
scribles.removeElement(persona);
}
public void inPeeps(String persona)
{
connectedPeeps.addElement(persona + " is online()" );
}

public Vector newEntry()


{
Vector temp = new Vector();
if(chat.size() > 10 )
{
temp.addElement(" Lastest 10 active Chats :" );
for(int i = chat.size() - (10 + 1 ) ; i < chat.size() ; i++)
temp.addElement( (String)chat.get(i) );
temp.addElement("-------------------------------------" );
}
temp.addElement("People who are ACTIVE : "+ numPopulation());
if( connectedPeeps.size() > 1 )
{
for(int i = 0; i < connectedPeeps.size() ; i++)
temp.addElement( (String)connectedPeeps.get(i) );
}
temp.addElement("----------START CHATTING!-------------" );
return temp;
}
public int numPopulation()
{
return scribles.size();
}

}
Eigenvalues
and
Eigenvectors
Eigenvalues.cpp

The German adjective eigen means “own” or “characteristic of”, eigenvalues and eigenvectors are
characteristic of a matrix in the sense that they contain important information about the nature of the
matrix, To find eigenvalues and eigenvectors of a symmetrical matrix over R one often uses the Jacobi
method. It consists of a sequence of orthogonal similarity transformation of the form

A → Q1− 1 AQ 1 → Q2− 1Q1− 1 AQ 1Q2 → ...

Let 1 ≤ p < r ≤ n. the basic Jacobi rotation matrix Q is a matrix with

q pp = q rr = cos θ , qii = 1 → i ≠ p, r
q pr = − q rp = − sin θ , qip = q pi = qir = q ri = 0 → i ≠ p, r
qij = 0 → i ≠ p, r ∩ j ≠ pr .

The idea of the Jacobi method is to try to zero off diagonals elements by a series of plane rotations.

/* */
/* eigenvalues.cpp */
/* original authors: */
/* Sifiso "BlackCid" Thwala */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

#include <iostream>
#include <cmath>
using namespace std;

int main(void)
{
const int M = 4, np = 4, n = 4;
int j, iq, ip, i, nrot;
double tresh, theta, tau, t, sm, s, h, g, c;

double A[M][M], v[M][M], d[M], b[M], z[M];


A[0][0] = 1.0/1.0;A[0][1] = 1.0/2.0;
A[0][2] = 1.0/3.0;A[0][3] = 1.0/4.0;
A[1][0] = 1.0/2.0;A[1][1] = 1.0/3.0;
A[1][2] = 1.0/4.0;A[2][3] = 1.0/5.0;
A[2][0] = 1.0/3.0;A[2][1] = 1.0/4.0;
A[2][2] = 1.0/5.0;A[2][3] = 1.0/6.0;
A[3][0] = 1.0/4.0;A[3][1] = 1.0/5.0;
A[3][2] = 1.0/6.0;A[3][3] = 1.0/7.0;
for(ip = 0; ip < n; ip++)
for(iq = 0; iq < n;iq++)
v[iq][ip] = 1.0;
for(ip = 0; ip < n; ip++)
{
b[ip] = A[ip][ip];
d[ip] = b[ip];
z[ip] = 0.0;
}
nrot = 0;

for( i = 0; i < 100; i++ )


{
sm = 0.0;
for( ip = 0; ip < (n-1); ip++)
for( iq = 0; iq < n; iq++)
sm += fabs(A[ip][iq]);
if( i < 6 ) tresh = 2.0*sm/pow(n,2.0); // A ware that the pow func sometime malfunctions
else tresh = 0.0;

for( ip = 0; ip < (n-1); ip++)


for( iq = 0; iq < n; iq++)
{
g = 100.0*fabs(A[ip][iq]);
if( ( ( i > 6) && ( (fabs(d[ip]) + g ) == fabs(d[ip]) ) && ( ( fabs(A[ip][iq])+ g ) == fabs( d[ip] ) ) ) )
A[ip][iq] = 0.0;
else if( fabs( A[ip][iq] ) > tresh )
{
h = d[iq] - d[ip];
if( ( fabs(h) + g ) == fabs(h) ){ t = A[ip][iq]/h; }
else
{
theta = 0.5*h/A[ip][iq];
t = 1.0/( fabs(theta) + sqrt(1.0 + pow(theta,2.0)));
if(theta < 0.0) t = -t;
}
c = 1.0/sqrt(1.0+pow(t,2.0));
s = t*c;
tau = s/(1.0 + c);
h = t*A[ip][iq];
z[ip] = z[ip] - h; z[iq] = z[iq] + h;
d[ip] = d[ip] - h; d[iq] = d[iq] + h;
A[ip][iq] = 0.0;

for( j = 0; j <(ip - 1) ; j++ )


{
g = A[j][ip]; h = A[j][iq];
A[j][ip] = g - s*(h+g*tau); A[j][iq] = h + s*(g-h*tau);
}

for( j = ip+1; j < (iq-1); j++ )


{
g = A[ip][j]; h = A[j][iq];
A[ip][j] = g - s*(h+g*tau); A[j][ip] = h + s*(g-h*tau);
}
for( j = iq+1; j < n; j++ )
{
g = A[iq][j]; h = A[iq][j];
A[iq][j] = g - s*(h+g*tau); A[iq][j] = h + s*(g-h*tau);
}

for( j = 0; j < n; j++)


{
g = v[j][ip]; h = v[j][iq];
v[j][ip] = g - s*(h+g*tau);v[j][iq] = h - s*(g-h*tau);
}
nrot++;
}
}
}

for( ip = 0; ip < n; ip++)


{
b[ip] = b[ip] + z[ip];
d[ip] = b[ip];
z[ip] = 0.0;
}

for( i = 0; i < np; i++)


{
cout << "When i = "<< i << " then d[" << i << "] = " << d[i] << endl;
system("pause");

}
return 0;
}
Matrix
This is a class that was created purely to be generic. IT is one of my ventures of studying C# and its syntax.
The Matrix class is simple textbook work – in fact I just took my old text book from the shelf - and merely
spans in the regular and generic cases of a typical matrix.
The UML diagram of the class:

Matrix

- Mat : double [ , ]

+ <<constructor>> Matrix()
+ Clone() : Object
+ Equals( in b : Object) : boolean
+ <<operator +>> Matrix ( a : Matrix, b : Matrix )
+ <<operator ->> Matrix ( a : Matrix, b : Matrix )
+ <<operator *>> Matrix ( a : Matrix, b : Matrix )
+ <<operator *>> Matrix ( a : Matrix, b : Vector )
+ Transpose() : Matrix
+ Translate( v : Vector ) : Matrix
+ Scale ( s : double ) : Matrix
+ Scale ( sx : double, sy : double, sz :double ) : Matrix
+ Rotate ( axis : Vector, angle : double ) : Matrix
+ Projection ( n : double, f : double , t : double, b : double, l : double, r : double ) : Matrix

+ ToString() : string

/* c# generic class */
/* Matrix.cs */
/* Created by: */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

using System;

public class Matrix


{
// only attribute
private double [,] mat;

// constructor
public Matrix()
{
// create an identity Matrix
int row, col;
mat = new double[4,4];
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(row == col)
mat[row,col] = 1.0;
else
mat[row,col] = 0.0;
}
}
}

public object Clone()


{
Matrix m = new Matrix();
int row,col;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
m[row,col] = mat[row,col];
}
}
}

public override bool Equals(object b)


{
Matrix m = (Matrix)b;
int row,col;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(m[row,col] != mat[row,col]) return false;
}
}
return true;
}
// index operator, to retrieve and set values
// in the matrix
public double this [int row, int col]
{
get { return mat[row,col]; }
set { mat[row,col] = value }
}
//arithmetic opearators
public static Matrix operator+(Matrix a,Matrix b)
{
int row, col;
Matrix r = new Matrix();
Matrix m = new Matrix();
int row,col;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
r[row,col] = a[row,col]+b[roe,col];
}
}
return r;
}
public static Matrix operator-(Matrix a,Matrix b)
{

Matrix r = new Matrix();

int row,col;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
r[row,col] = a[row,col]-b[roe,col];
}
}
return r;
}
public static Matrix operator*(Matrix a,Matrix b)
{

Matrix r = new Matrix();

int row, col, i;


for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
r[row,col] = 0;
for( i = 0; i < 4 ; i++)
{
r[row,col] += a[row,col]*b[roe,col];
}
}
}
return r;
}
public static Vector operator*(Matrix a, Vector v)
{
Vector r = new Vector();
r.x = v.x*a[0,0] + v.y*a[0,1] + v.z*a[0,2] + v.w*a[0,3];
r.y = v.x*a[1,0] + v.y*a[1,1] + v.z*a[1,2] + v.w*a[1,3];
r.z = v.x*a[2,0] + v.y*a[2,1] + v.z*a[2,2] + v.w*a[2,3];
r.w = v.x*a[3,0] + v.y*a[3,1] + v.z*a[3,2] + v.w*a[3,3];
return r;
}
public Matrix Transpose()
{
Matrix r = new Matrix();
int row,col;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
r[row,col] = mat[col,row];
}
}
return r;
}
public static Matrix Translate(Vector t)
{
Matrix m = new Matrix();
m[0,3] = t.x;
m[1,3] = t.y;
m[2,3] = t.z;
return m;
}
public static Matrix Scale(double s)
{
Matrix m = new Matrix();
m[0,2] = s;
m[1,2] = s;
m[2,2] = s;
return m;
}
public static Matrix Scale(double sx, double sy, double sz)
{
Matrix m = new Matrix();
m[0,2] = sx;
m[1,2] = sy;
m[2,2] = sz;
return m;
}
//general rotation around the vector axis
public static Matrix Rotate(Vector axis, double angle)
{
Matrix r = new matrix ();
double c = Math.Cos(angle);
double s = Mathe.Sin(angle);
axis.normalise();

r[0,0] = (1-c)*axis.x*axis.x + c;
r[1,0] = (1-c)*axis.x*axis.y + s*axis.z;
r[2,0] = (1-c)*axis.x*axis.z - s*axis.y;
r[3,0] = 0;

r[0,1] = (1-c)*axis.x*axis.y - s*axis.z ;


r[1,1] = (1-c)*axis.y*axis.y + c;
r[2,1] = (1-c)*axis.y*axis.z + s*axis.x;
r[3,1] = 0;

r[0,2] = (1-c)*axis.x*axis.z + s*axis.y;


r[1,2] = (1-c)*axis.y*axis.z - s*axis.x;
r[2,2] = (1-c)*axis.z*axis.z + c;
r[3,2] = 0;

r[0,3] = 0;
r[1,3] = 0;
r[2,3] = 0;
r[3,3] = 0;

return r;
}
public static Matrix Projection(double n,double f, double t,double b,double l,double r)
{
Matrix m = new Matrix();
m[0,0] = 2*n/(r-1);
m[1,0] = 0;
m[2,0] = 0;
m[3,0] = 0;

m[0,1] = 0;
m[1,1] = 2*n/(t-b);
m[2,1] = 0;
m[3,1] = 0;

m[0,2] = 0;
m[1,2] = 2*n/(t-b);
m[2,2] = -(f+n)/(f-n);
m[3,2] = -1;

m[0,3] = (r+1)/(r-1);
m[1,3] = (t+b)/(t-b);
m[2,3] = -2*f*n/(f-n);
m[3,3] = 0;
return m;
}
//providing a method to display the matrix
public override string ToString()
{
int i;
string s ="\n";
for( i = 0; i < 4; i++ )
{
s += string.Format("[{0},[1],[3]]\n",mat[i,0],mat[i,1],mat[i,2],mat[i,3]);
}
return s;
}
};
Grey Picture
Computer graphics program seldom take the structure and functioning of the eye into account. If they do,
the results usually take a very long time to produce.
One of the peculiarities of the eye (or camera) is focal length. A certain distance in the scene remains in fo-
cus, whereas closer (or further) objects appear to be blurred. A typical ray tracer program produces crystal
clear images for all distances. To make the result realistic, we would like to simulate the focal length or
depth of field. We thus need to be able to read images stored in binary format. The images provided for this
practical are gray files. The format of the gray file is as follows:

• One integer specifying the width (binary format).


• One integer specifying the height (binary format).
• The intensity of the each pixel in the grid that is width × height values of type unsigned char.

The values in the image indicate the intensity with 0 being black and 255 white. The values in between spe-
cify shades of gray. You are also given a depth image of exactly the same size and format.
However, the values are interpreted as:

• 0 - very, very near.


• 255 – very, very far.
• Any value in between - somewhere between near and far!

Load both an image and its depth map into separate two dimensional dynamic arrays. Now, apply a Gaussi-
an filter:

1 2 2 2
G ( x, y ) = e − (( x − col ) + ( y − row ) ) /( 2 r ))
2π r 2

The 2D Gaussian function reaches a maximum in the centre:

For each pixel, we calculate the value r (given below) and then use a nested for loop to iterate from 3r rows
before to 3r rows afterward, and likewise for the columns. Multiply the Gaussian function by the intensity
at that position in the image and add the results together. Be sure to check whether the pixels are in bounds,
x and y refers to the pixel under consideration and G can be used to calculate the relative importance of the
pixel. We thus compute

row + 3 r col + 3 r
newimage [ row ][ col ] = ∑ ∑ G ( x, y )image [ y ][ x ]
y = row − 3 r x = col − 3 r
I used floating points to calculate the value and typecast back to an unsigned char afterward. The radius r is
determined by the focal length f,
r = | d − f | / 50
Where d = depth[row][col] is the depth value stored at the pixel. Make sure that r is at least 0.5.
For example, consider the image and depth map of a castle:

If a focal length of 128.0 is used results are:

And with a focal length of 240.0, results are:

The name of the image and depth map, as well as focal length must be passed through on the command
line. The resulting image must be written to file in gray format. A program will be included to view gray
files, and example data will be provided.
Images and scene files are provided by Gilles Tran.

Get the example or sample data from my site: http://www.BlackCid.co.za

This must be run via console passing the arguments: (gray image) (depth image)(focal length as an integer)
/* */
/* focal.cpp */
/* original authors: */
/* Sifiso "BlackCid" Thwala */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

#include <fstream>
#include <iostream>
#include <cmath>
#include <string>
#include <sstream>

using namespace std;

//This method returns the new colour value for a specific point
//by applying the gaussian formula
unsigned char gaussian(unsigned char **image, int row, int col, int w, int h, double r) {
int i, j;
r=fabs(r); //Get the absolute value of the guassian radius to work with
if (r<1) r=1;
int radius=(int)(r*3);
double e=M_E; //Get the value of e from the math library
double colour=0.0;
if (radius<1) radius=1;
for (i=-radius; i<=+radius; i++) {
for (j=-radius; j<=+radius; j++) {
if ((i+row>=0)&&(i+row<h)&&(j+col>=0)&&(j+col<w)) //If the guassian radi-
us is within the image boundary
colour+=pow(e, -(i*i+j*j)/(2*r*r))*image[i+row][j+col];
else //If the guassian radius is outside the image
boundary
colour+=pow(e, -(i*i+j*j)/(2*r*r))*128;
}
}
colour/=2*M_PI*r*r;

//Return the calculated colour


return (unsigned char)colour;
}

int main(int argc, char *argv[]) {


if (argc!=4) {
cout << "Usage: " << argv[0] << "gray_image depth_image focal_length" << endl;
cout << " the output file is saved as focal.gry" << endl;
return 0;
}

ifstream depth;
ifstream gray;
ofstream focal;
int w;
int h;
int dw;
int dh;
int row, col;
double focallen;
unsigned char **image;
unsigned char **z;
unsigned char **newimage;

string flen(argv[3]);
istringstream strin(flen);
strin >> focallen;

//Open the 2 files for reading and one for output


gray.open(argv[1], ios::binary|ios::in);
depth.open(argv[2], ios::binary|ios::in);
focal.open("focal.gry", ios::binary|ios::out);

//Read in the width and height of the grey+depth images


gray.read((char *)&w, sizeof(w));
gray.read((char *)&h, sizeof(h));
depth.read((char *)&dw, sizeof(dw));
depth.read((char *)&dh, sizeof(dh));

//If the depth map image is not equal to the grey image dimensions, quit
if ((dw!=w)||(dh!=h)) {
cout << "Picture does not match depth image dimensions" << endl;
return 1;
}

cout << w << "x" << h << endl;

//Create the 2D arrays


z=new unsigned char* [h];
image=new unsigned char* [h];
newimage=new unsigned char* [h];
for (row=0; row<h; row++) {
image[row]=new unsigned char[w];
z[row]=new unsigned char[w];
newimage[row]=new unsigned char[w];

//Read in the colour values from the images


gray.read((char *)image[row], w);
depth.read((char *)z[row], w);
}

for (row=0; row<h; row++) {


cout << row << " " << "\r"; cout.flush();
for (col=0; col<w; col++) {
//Set the values of the new images for each pixel
newimage[row][col]=gaussian(image, row, col, w, h, (z[row][col]-
focallen)/50.0);
}
}

//Write the width and height of the new image to file


focal.write((char *)&w, sizeof(w));
focal.write((char *)&h, sizeof(h));

for (row=0; row<h; row++) {


//Write the colour values of the new image to file
focal.write((char *)newimage[row], w);
}

//Free allocated memory


for (row=0; row<h; row++) {
delete[] newimage[row];
delete[] z[row];
delete[] image[row];
}
delete[] newimage;
delete[] image;
delete[] z;

gray.close();
depth.close();
focal.close();

return 0;
}
GIMP
A computer image is made up of tiny elements called pixels (picture elements). Each element is composed
of differing values of the colours red, green and blue called RGB values. These are often represented as a
set of three numbers ranging from 0-255. For example 0 means that none of that particular colour is in-
cluded and 255 means that all of that colour component is included. The colour Red for example would be
represented as 255 0 0, Blue as 0 0 255 and Green as 0 255 0
Christian Faur[1] is an artist who has devised a mapping between colours and characters in the Latin alpha-
bet where the most striking colours (as measured by human perception tests) are mapped onto the most fre-
quently used letters in the English language.
Mr. Faur’s mapping is as follows (used with the permission of the artist):

The portable pixel map[2] (.ppm) file format is a very simple text-based file format for representing graph-
ical images. We will be using a simplified* version of the format as follows:
P3
#generated by <executable name>
Image-width image-height
Max-value-for-rgb
R G B R G B R G B…
R G B R G B R G B…
R G B R G B R G B…
.
*our simplified version will ignore the 70 character line limit so that one line of our image is equal to one
line of RGB values in the PPM file.
In order to view one of our PPM files you will need to use an imaging tool a little more sophisticated than
MS-Paint. I highly recommend using The GIMP[3] (GNU Image Manipulation Program) which is both
open source and extremely capable. An example PPM file encoding the string “Hello World” is available
under the additional files section of this practical. The example file would appear visually as follows when
loaded into the GIMP.

[1] http://www.christianfaur.com/conceptual/colorAlphabet/index.html
[2] http://netpbm.sourceforge.net/doc/ppm.html
[3] http://www.gimp.org/

/* */
/* main.cpp */
/* original authors: */
/* Sifiso "BlackCid" Thwala */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

#include <string>
#include <iostream>
#include <cstdlib>
#include "omniglot.h"
#define CLI_ERROR -1
using namespace std;
int main(int argc, char** argv)
{
if(argc != 3)
{
cout << "Usage: omniglot operation filename" << endl
cout << "Values for operation: " << endl
cout << "encode: Transcribe from English to ColourAlphabetimage" <<endl
cout << "decode: Transcribe from ColourAlphabet image to English"<< endl;
return CLI_ERROR;
}
string strPath = argv[2];
ColourAlphabetTranscriber transcriber;
string strMessage;
if(strcmp(argv[1],"decode") == 0)
{
strMessage = transcriber.transcribeImage(strPath);
cout << strMessage;
}else if (strcmp(argv[1],"encode") == 0)
{
cout << "Enter message to transcribe: ";
char c;
while(c != '\n')
{
if(isalpha(c) || c == ' ')
strMessage += c;
cin.get(c);
}
transcriber.transcribeText(strPath, strMessage);
}else
{
cout << "Unsupported operation " << argv[1] << endl;
}
return 0;
}

/* */
/* OMNIGLOT.cpp */
/* original authors: */
/* Sifiso "BlackCid" Thwala */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

#include <fstream>
#include <iostream>
#include <cstdlib>
#include <string>
#include <sstream>

#include "omniglot.h"

using namespace std;

Transcriber::Transcriber()
{
}

ColourAlphabetTranscriber::ColourAlphabetTranscriber()
{
this->c.block_height = 50;S
this->c.block_width = 25;
}

ColourAlphabetTranscriber::ColourAlphabetTranscriber(CATConfig c)
{
this->c =c;
}

string ColourAlphabetTranscriber::transcribeImage(string strPath)


{
string strMessage = "";
int msg_length = 0;
RGBColour* a = readImage(strPath, msg_length);
for(int k = 0; k < msg_length; k++)
strMessage += mapColour(a[k]);

delete [] a;
return strMessage + "\n";
}

RGBColour* ColourAlphabetTranscriber::readImage(string strPath, int &length)


{
RGBColour* aryReturn = NULL;
ifstream in;
in.open(strPath.c_str());
if(in.fail())
{
cout << "Error opening " + strPath << endl;
return NULL;
}

string strLine;
getline(in, strLine);
if(strLine != "P3")
{
cout << "Error invalid PPM file header" << endl;
return NULL;
}

string strWidth, strHeight;


getline(in, strLine);
in >> strWidth; in >> strHeight;
int width, height;
width = atoi(strWidth.c_str());
height = atoi(strHeight.c_str());
getline(in, strLine);
getline(in, strLine);
getline(in, strLine);
in.close();

length = width / this->c.block_width;


aryReturn = new RGBColour[length];
stringstream ssLine(strLine);
int block_count =0;
int pixel_count = 0;
int line_char_count = strLine.length() - 1;
bool isDone = false;
while(!isDone)
{
int red, green, blue, current_pos;
ssLine >> red >> green >> blue;
if((pixel_count == 0) || (pixel_count == this->c.block_width))
{
aryReturn[block_count] = mapColour(red, green, blue);
block_count++;
pixel_count = 0;
}
pixel_count++;
current_pos = (int)ssLine.tellg();
isDone = (current_pos == (line_char_count));
}
return aryReturn;
}

bool ColourAlphabetTranscriber::writeImage(string strPath, RGBColouraryMessage[], int length)


{
ofstream out;
out.open(strPath.c_str());
if(out.fail())
{
cout << "Error creating file " << strPath << endl;
return false;
}
out << "P3" << endl;
out << "# Generated by Omniglot::ColourAlphabetTranscriber" << endl;
out << (length * this->c.block_width) << " " << this->c.block_height<< endl;
out << "255" << endl;
for(int h = 0; h < this->c.block_height; h++)
{
for(int k = 0; k < length; k++)
{
for(int l = 0; l < this->c.block_width; l++)
{
out << aryMessage[k].red << " ";
out << aryMessage[k].green << " ";
out << aryMessage[k].blue << " ";
}
}
out << endl;
}
out.close();
return true;
}

void ColourAlphabetTranscriber::transcribeText(string strPath, stringstrMessage)


{
RGBColour a[strMessage.length()];
int msg_length = strMessage.length();
for(int k = 0; k < msg_length; k++)
a[k] = mapColour(strMessage[k]);
writeImage(strPath, a, msg_length);
}

char ColourAlphabetTranscriber::mapColour(RGBColour c)
{
if(c.red == 255 && c.green == 255 && c.blue == 150)
return 'K';
if(c.red == 205 && c.green == 145 && c.blue == 63)
return 'M';
if(c.red == 202 && c.green == 62 && c.blue == 94)
return 'L';
if(c.red == 255 && c.green == 152 && c.blue == 213)
return 'W';
if(c.red == 83 && c.green == 140 && c.blue == 208)
return 'T';
if(c.red == 178 && c.green == 220 && c.blue == 205)
return 'V';
if(c.red == 146 && c.green == 248 && c.blue == 70)
return 'C';
if(c.red == 175 && c.green == 200 && c.blue == 74)
return 'Y';
if(c.red == 185 && c.green == 185 && c.blue == 185)
return 'F';
if(c.red == 235 && c.green == 235 && c.blue == 222)
return 'G';
if(c.red == 255 && c.green == 255 && c.blue == 0)
return 'I';
if(c.red == 255 && c.green == 200 && c.blue == 47)
return 'D';
if(c.red == 255 && c.green == 118 && c.blue == 0)
return 'E';
if(c.red == 255 && c.green == 0 && c.blue == 0)
return 'O';
if(c.red == 175 && c.green == 13 && c.blue == 102)
return 'B';
if(c.red == 121 && c.green == 33 && c.blue == 135)
return 'S';
if(c.red == 0 && c.green == 0 && c.blue == 180)
return 'A';
if(c.red == 12 && c.green == 75 && c.blue == 100)
return 'N';
if(c.red == 0 && c.green == 154 && c.blue == 37)
return 'U';
if(c.red == 100 && c.green == 100 && c.blue == 100)
return 'H';
if(c.red == 175 && c.green == 155 && c.blue == 50)
return 'P';
if(c.red == 63 && c.green == 25 && c.blue == 12)
return 'Z';
if(c.red == 55 && c.green == 19 && c.blue == 112)
return 'J';
if(c.red == 0 && c.green == 0 && c.blue == 74)
return 'X';
if(c.red == 37 && c.green == 70 && c.blue == 25)
return 'R';
if(c.red == 0 && c.green == 0 && c.blue == 0)
return 'Q';
return (c.red == 255 && c.green == 255 && c.blue == 255) ? ' ' : '!';
}

RGBColour ColourAlphabetTranscriber::mapColour(int red, int green, int blue)


{
RGBColour rgb = {red,green,blue};
return rgb;
}

RGBColour ColourAlphabetTranscriber::mapColour(char c)
{
switch(toupper(c))
{
case 'A': return mapColour(0,0,180);
case 'B': return mapColour(175,13,102);
case 'C': return mapColour(146,248,70);
case 'D': return mapColour(255,200,47);
case 'E': return mapColour(255,118,0);
case 'F': return mapColour(185,185,185);
case 'G': return mapColour(235,235,222);
case 'H': return mapColour(100,100,100);
case 'I': return mapColour(255,255,0);
case 'J': return mapColour(55,19,112);
case 'K': return mapColour(255,255,150);
case 'L': return mapColour(202,62,94);
case 'M': return mapColour(205,145,63);
case 'N': return mapColour(12,75,100);
case 'O': return mapColour(255,0,0);
case 'P': return mapColour(175,155,50);
case 'Q': return mapColour(0,0,0);
case 'R': return mapColour(37,70,25);
case 'S': return mapColour(121,33,135);
case 'T': return mapColour(83,140,208);
case 'U': return mapColour(0,154,37);
case 'V': return mapColour(178,220,205);
case 'W': return mapColour(255,152,213);
case 'X': return mapColour(0,0,74);
case 'Y': return mapColour(175,200,74);
case 'Z': return mapColour(63,25,12);
case ' ': return mapColour(255,255,255);
}
return mapColour(255,255,255);
}

/* */
/* OMNIGLOT.h */
/* original authors: */
/* Sifiso "BlackCid" Thwala */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

#ifndef OMNIGLOT_H
#define OMNIGLOT_H
#include <string>
using namespace std;
struct RGBColour
{
int red, green, blue;
};

struct CATConfig
{
int block_height, block_width;
};
class Transcriber
{
public:
Transcriber();
};

class ColourAlphabetTranscriber : public Transcriber


{
public:
ColourAlphabetTranscriber();
ColourAlphabetTranscriber(CATConfig c);
string transcribeImage(string strPath);
void transcribeText(string strPath, string strMessage);
private:
CATConfig c;
char mapColour(RGBColour c);
RGBColour mapColour(char c);
RGBColour mapColour(int red, int green, int blue);
RGBColour* readImage(string strPath, int& length);
bool writeImage(string strPath, RGBColour aryMessage[], int length);
};
#endif
Bézier curve
Bezier.java

A Bézier curve B(t) of degree n is defined by a set of control points pi for i = 0,1,..., n as follows:
n
B (t ) = ∑
i= 0
pi Bi ,n (t )

Where Bi ,n are the Bernstein polynomials:


Bi , n (t ) ?= nCit i (1 − t ) n − i
The sum of the Bernstein polynomials is a partition of unity
n


i= 0
Bi , n (t ) = 1

We have Bi , n (t ) ≥ 0 to every 0 ≤ t ≤ 1 . The properties imply that the Bézier curves are affine invariant
and that the curve lies entity in the convex hull of the control points defining the curve. We find that
B (0) = p0 and that B (1) = pn . Thus, the Bézier curve interpolates the end points, we find that
dB dB
(0) = n( p1 − p0 ) , (1) = n( pn − pn − 1 )
dt dt
Thus the tangents at the end points of the curve are easily computed. This allows us to construct piecewise
smooth C 1orG1 curve out of Bézier curves by setting n p ( p1 − p0 ) = cnq (qn − qn − 1 ) for a curve
nq

Q(t ) = ∑i= 0
qi Bi , n (t )
Followed by a curve
np

P (t ) = ∑
i= 0
pi Bi , n (t )

The Java Applet displays the Bézier curve

/* Bézier.java */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */
import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.awt.Graphics;
import java.util.Vector;
class Vertex
{
public double x,y;
public boolean selected;
public Vertex(double x, double y)
{
this.x = x; this.y = y;
selected = false;
}
}

class BezierPanel extends Panel implements MouseListener, MouseMotionListener


{
private int n = 0;
private double delta = 0.0001;
private Vector vertices = new Vector();
private boolean drawcurve;
private double a[], b[], c[], d;
private double cost, sint;

public BezierPanel()
{
n = 0;
addMouseListener(this);
addMouseMotionListener(this);
drawcurve = true;
}
public void mouseMoved(MouseEvent e){ drawcurve = true; }
public void mouseDragged(MouseEvent e)
{
Vertex p;
e.consume();
for(int k =0; k < n; k++)
{
p = (Vertex)vertices.elementAt(k);
if(p.selected){ p.x = e.getX(); p.y = e.getY(); }
}
repaint();
}

public void mousePressed(MouseEvent e)


{
Vertex p;
e.consume();
for(int k = 0; k < n; k++)
{
p = (Vertex)vertices.elementAt(k);
if((Math.abs(e.getX() - p.x) < 3) && ( Math.abs(e.getY() - p.y) < 3 ))
p.selected = true;
else
p.selected = false;
}
drawcurve = false;
repaint();
}

public void mouseReleased(MouseEvent e)


{ drawcurve = true;repaint(); }

public void mouseEntered(MouseEvent e) { /* Do nothing */ }


public void mouseExited(MouseEvent e){ /* Do nothing */ }
public void mouseClicked(MouseEvent e)
{
e.consume();
if(e.getButton() == MouseEvent.BUTTON3)
{
n = 0;
vertices.clear();
}else
{
vertices.add(new Vertex(e.getX(),e.getY() ) );
}
drawcurve = true;
repaint();
}

public int comb(int t, int b)


{
int r = 1;
for(int i = b+1; i <= t; i++) r *= i;
for(int i = 2; i <= (t-b); i++) r /= i;
return r;
}

public double Bernstein(int i, int n, double t)


{ return comb(n,i)*Math.pow(t,i)*Math.pow(1.0 - t, n-i); }

public void paint(Graphics g)


{
double x, y, oldx, oldy, t = 0.0;
int i, j, count;
double num, den;
Vertex p;
for( i = 0; i < n; i++)
{
p = (Vertex)vertices.elementAt(i);
x = p.x; y = p.y;
if(p.selected) g.setColor(Color.red);
else g.setColor(Color.green);
g.fillRect( (int)x - 3, (int)y - 3,6,6);
}
g.setColor(Color.red);
for( i = 1; i < n; i++)
{
p = (Vertex)vertices.elementAt(i);
x = p.x; y = p.y;
p = (Vertex)vertices.elementAt( i - 1 );
oldx = p.x; oldy = p.y;
g.drawLine( (int)oldx, (int)oldy, (int)x, (int)y );
}
if(!drawcurve) return;
g.setColor(Color.black);
if(n < 3) return;
oldx = oldy = 0.0;
for( i = 0; i < n; i++ )
{
p = (Vertex) vertices.elementAt(i);
oldx += Bernstein( i, n - 1, t)*p.x;
oldy += Bernstein( i, n - 1, t)*p.y;
}
for( t = 0; t <= 1.0; t += delta)
{
x = y = 0.0;
for( i = 0; i < n; i++)
{
p = (Vertex)vertices.elementAt(i);
x += Bernstein( i, n - 1, t)*p.x; y += Bernstein( i, n - 1, t)*p.y;
}
g.drawLine( (int)oldx, (int)oldy, (int)x, (int)y );
oldx = x; oldy = y;
}
}
}

public class Bezier extends java.applet.Applet implements WindowListener


{
BezierPanel panel;
static Frame f;
public void windowActivated(WindowEvent e){};
public void windowClosed(WindowEvent e){};
public void windowClosing(WindowEvent e){
remove(panel);
panel = null;
f.dispose(); f = null;
};
public void windowDeactivated(WindowEvent e){};
public void windowDeiconified(WindowEvent e){};
public void windowIconified(WindowEvent e){};
public void windowOpened(WindowEvent e){};

public void init()


{
setLayout(new BorderLayout());
panel = new BezierPanel();
add("Center",panel);
}

public void destroy() { remove(panel); panel = null; }

public static void main(String args[])


{
f = new Frame("Bezier curve");
Bezier h = new Bezier();
h.init(); h.start();
f.add("Center",h);
f.setSize(300,300);
f.show();
f.addWindowListener(h);
}

public String getAppletInfo()


{ return "Draw a Bezier curve between points"; }
}
Harmonic interpolation
Harmonicinterpolation.java
The n × n primary permutation matrix U is given by
0 1 0  0
0 0 1  0
 
U =     
0 0 0  1
 
 1 0 0  0
The eigenvalues of U are given by λ 0 = 1, λ 1 , λ 2 ,... λ n − 1with λ := exp( 2π i / n) . The spectral
decomposition of U is:
n− 1
U= ∑
j= 0
λ j Pj .

The projection matrix p j can be expressed using U k . Since Pj Pk = 0 for j ≠ k and Pj2 = Pj we find:
n− 1
Uk = ∑
j= 0
λ j Pj k = 1,2,..., n.

Thus, we calculated the Fourier transform of the projection matrices. For k = n we have U n = I n and the
completeness relation:
n− 1
In = ∑j= 0
Pj

(λ jk ) is given by 1 n (λ ) . Thus
− jk
The inverse of the matrix
n− 1

n∑
Pj = 1 λ − jkU k , j = 0,1,..., n − 1.
k= 0
We apply the permutation in such a way that we can continuously interpolate between the points of the
polygon. We embed the matrices U k into a real Lie group. Thus we have to consider the cases n = 2m + 1
and n = 2m, where m is a positive integer. In the second case we have λ 0 = 1 and λ m = − 1 . Furthermore,
we define P− j := Pn − 1. The projection matrices are therefore real. We consider first case n = 2m +1. we
obtain by replacing k by nt , t ∈ [ 0,1]
m
~
U (t ) = P0 + ∑j= 1
(e 2π ijt Pj + e − 2π ijt P− j ), t ∈ ℜ

~ ~ ~ ~ ~
The unitary matrices U (t ) are 1-periodic, i.e. U (t + 1) = U (t ) . Thus U (t + 1) = U (t ) and
~ ~
U ( k / n) = U k fork = 0,1,..., n − 1 . Owing to the previous, we can write U (t ) as:
n− 1 m
~
n∑ ∑
U (t ) = 1 (1 + (e 2π ij (t − k / n ) + e − 2π ij (t − k / n ) ))U k
k=1 j= 1

m
1
We define: δ k (t ) ≡ δ (t − k / n):=
n
(1 + ∑
j= 1
(e 2π ij (t − k / n ) + e 2π ij (t − k / n ) ))

sin(π n(t − k / n))


Using exp(iα ) ≡ cos α + i sin α , : δ k (t ) = , k = 0,1,..., n − 1
n sin(π (t − k / n))
n− 1
~
Thus we can write: U (t ) = ∑k= 0
δ k (t )U K

n− 1 n− 1
We have the properties: ∑
k= 0
δ k (t ) = 1 ∑
k= 0
δ k2 (t ) = 1.

thus the functions δ k (t ) and δ k (t ) provide a partition of unity and the harmonic interpolation is affine
2

invariant. Now let x = ( x0 , x1 ,..., xn − 1 ) be the vector which describes the polygon. Then
T

n− 1
~
X (t ) = U (t ) X = = ∑ δ (t − k / n)U k X
k= 0

The curve which describes our closed smooth curve is given by:
n− 1 n− 1
X l (t ) = ∑
k= 0
δ (t − k / n) X k + l = ∑
k = .0
δ (t + l / n − (k + l ) / n) X k + l = X 0 (t + l / n)

Where ( k + l ) is calculated mod n. Hence, for all l it represents the same curve and we can write:
n− 1
X (t ) = ∑
k= 0
δ (t − k / n) X k , t ∈ [0,1]

Thus this curve interpolates the points of the given polygon smoothly. We consider now the case n = 2m.
for this case we may write:
m− 1
U k = P0 + (− 1) k Pm + ∑j= 1
(λ jk Pj + λ − jk P− j ).

If we replace the discrete variable k by the real variable t, we find the factor (− 1) k ≡ e π it The other terms
are real. Thus, t the Lie group we could find is not real and therefore cannot be used directly for the
harmonic interpolation in computer graphics. Since the function U(t) will be continuous in the complex
domain and go through the points of the polygon. A similar calculation as described for the case n = 2m +1
given above yields (t ∈ [0,1])
n− 1 n− 1 n− 1
~
n∑ n∑ ∑
U (t ) = 1 cos(π (nt − k ))U k + 1 sin(π (nt − k ))U k + ξ k (t )U k
k= 0 k= 0 k= 0

sin(π (nt − k ))
Where: ξ (t ) := , ξ (t ) := ξ (t − k / n)
n sin(π t )
Thus, our smooth curve in the even case which goes through all the points of the polygon is:
n− 1
X (t ) = ∑ k= 0
( 1 cos(π (nt − k )) + ξ k (t )) X k
n
`Most calculations and deductions were guided by Prof. A hardy and Prof.WH Steeb
The java applet and application draw the harmonic interpolation of a polygon.

/* HarmonicInterpolation.java */
/* original authors: */
/* WH Steeb, Yorick and Alexandre Hardy and R Stoop */
/* http://issc.rau.ac.za */
/* Edited and modified */
/* Sifiso "BlackCid" Thwala */
/* http://www.BlackCid.co.za */
/* */

import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.awt.Graphics;
import java.util.Vector;

class Vertex
{
public double x, y;
public boolean selected;
public Vertex(double x,double y)
{
this.x = x; this.y = y;
selected = false;
}
}

class HarmonicPanel extends Panel implements MouseListener, MouseMotionListener


{
private int n = 0;
private double delta = 0.0001;
private Vector vertices = new Vector();
private boolean drawcurve;
private double a[], b[], c[], d;
private double cost, sint;

public HarmonicPanel()
{
n = 0;
addMouseListener(this);
addMouseMotionListener(this);
drawcurve = true;
}

public void mouseMoved(MouseEvent e) { drawcurve = true;}


public void mouseDragged(MouseEvent e)
{
Vertex p;
e.consume();
for(int k = 0; k < n; k++)
{
p = (Vertex)vertices.elementAt(k);
if(p.selected){ p.x = e.getX(); p.y = e.getY(); }
}
repaint();
}

public void mousePressed(MouseEvent e)


{
Vertex p;
e.consume();
for(int k = 0; k < n; k++)
{
p = (Vertex)vertices.elementAt(k);
if( (Math.abs(e.getX() - p.x ) < 3 ) && (Math.abs(e.getY() - p.y) < 3 ))
p.selected = true;
else p.selected = false;
}
drawcurve = false;
repaint();
}

public void mouseReleased(MouseEvent e) { drawcurve = true;repaint(); }


public void mouseEntered(MouseEvent e) { /* do nothing*/ }
public void mouseExited(MouseEvent e) { /* do nothing*/ }
public void mouseClicked(MouseEvent e)
{
e.consume();
if(e.getButton() == MouseEvent.BUTTON3)
{
n = 0;
vertices.clear();
}else
{
n++ ; vertices.add(new Vertex( e.getX(),e.getY() ));
}
drawcurve = true;
repaint();
}

public double sigma_helper(int n, double t)


{
if(n == 1) return 1;
return Math.cos(Math.PI*(n-1)*t)+Math.cos(Math.PI*t)*sigma_helper(n-1,t);
}

private double sigma( double t)


{
double result;
double test = Math.abs(t)-(int)(Math.abs(t));
double dist1= test, dist2 = Math.abs(1.0 - test);
if( ( dist1 < 1e-7 )||( dist2 < 1e-7) ) result = sigma_helper(n, t)/n;
else result = Math.sin(Math.PI*n*(t))/(n*Math.sin(Math.PI*(t)));
if( n % 2 == 0 ) return result *= Math.cos(Math.PI*t);
return result;
}

private double sigma_k( int k, double t){ return sigma(t -(double)k/n); }

public void paint(Graphics g)


{
double x, y, oldx, oldy, num, den;
int k, j, count;
double t = 0.0;
Vertex p;
for( k = 0; k < n; k++ )
{
p = (Vertex)vertices.elementAt(k);
x = p.x; y = p.y;
if( p.selected ) g.setColor(Color.red);
else g.setColor(Color.green);
g.fillRect((int)x - 3,(int)y - 3, 6, 6);
}
g.setColor(Color.red);
for( k = 0; k < n; k++ )
{
p = (Vertex)vertices.elementAt(k);
x = p.x; y = p.y;
p = (Vertex)vertices.elementAt(k-1);
oldx = p.x; oldy = p.y;
if( p.selected ) g.setColor(Color.red);
g.drawLine( (int)oldx,(int)oldy, (int)x, (int)y);
}
g.setColor(Color.blue);
if( n > 2)
{
p = (Vertex)vertices.elementAt(0);
x = p.x; y = p.y;
p = (Vertex)vertices.elementAt(n-1);
oldx = p.x; oldy = p.y;
if( p.selected ) g.setColor(Color.red);
g.drawLine( (int)oldx,(int)oldy, (int)x, (int)y);
}
if(!drawcurve) return;
g.setColor(Color.black);
if( n < 3 ) return;
oldx = oldy = 0.0;
for( k = 0; k < n; k++)
{
p = (Vertex)vertices.elementAt(k);
oldx += sigma_k(k, t)*p.x; oldy += sigma_k(k, t)*p.y;
}
for( t = 0; t < 1.0; t += delta )
{
x=y=0.0;
for( k = 0; k < n; k++ )
{
p = (Vertex)vertices.elementAt(k);
x += sigma_k(k, t)*p.x; y += sigma_k(k, t)*p.y;
}
g.drawLine((int)oldx, (int)oldy, (int)x, (int)y);
oldy = x; oldy = y;
}
}
}

public class HarmonicInterpolation extends Applet implements WindowListener


{
HarmonicPanel panel;
static Frame f;

public void windowActivated(WindowEvent e) { /* do nothing*/ };


public void windowClosed(WindowEvent e) { /* do nothing*/ };
public void windowClosing(WindowEvent e)
{ remove(panel); panel = null; f.dispose(); f = null; };
public void windowDeactivated(WindowEvent e) { /* do nothing*/ };
public void windowDeiconified(WindowEvent e) { /* do nothing*/ };
public void windowIconified(WindowEvent e) { /* do nothing*/ };
public void windowOpened(WindowEvent e) { /* do nothing*/ };

public void init()


{
setLayout(new BorderLayout());
panel = new HarmonicPanel();
add("Center",panel);
}
public void destroy()
{ remove(panel); panel = null; }
public static void main(String[] args)
{
f = new Frame("Harmonic Intepolation");
HarmonicInterpolation h = new HarmonicInterpolation();
h.init(); h.start();
f.add("Center",h);
f.setSize(300,300);
f.show();
f.addWindowListener(h);
}
public String getAppletInfo()
{ return "Draw a curve using harmonic interpolation"; }
}
Bibliography
David Poole
Linear Algebra a modern introduction second edition
Thomson BROOKS/COLE (2006)

Akenine-Möller, T. and Haines E.


Real-Time Rendering, second edition
AK Peter, Natick, Massachusetts (2002)

Séroul R.
Programming for mathematicians
Springer Verlag, Belin (1991)

Wili-Hans Steeb, Yorick Hardy, Alexandre Hardy and Ruedi Stoop


Problem solving & solutions in scientific computing
World Scientific (2004)

Neapolitan R. and Naimipour K


foundations of Algorithms
D. C. Heath and company, Lexington (1996)

Bäck T.
Evolutionary Algorithms in Theory and Practice
Oxford University Press, Oxford (1996)

Baase S.
Computer algorithms, Second Edition
Addison-Wesley, Reading, Massechusetts(1988)

Вам также может понравиться