You are on page 1of 56

ORT Braude College, Karmiel, Course: Image Processing 31651

Lecturer: Dr. Samuel Kosolapov; ksamuel@braude.ac.il

Getting Started with


Three-Dimensional Projections
According to:
Graphics Programming with Microsoft C and Microsoft QuickC
Kris Jamsa
1990, Microsoft Press
Part IV: Three Dimensional Graphics; pp. 429-500.
Applications
• CAD (Computer Aided Design) Systems
• Architecture & Landscape design
• Furniture Design
• Computer Games
• Educational Software
• Illustration & Art
CAD Example: Pneumatic Cylinder (TurboCad 10.5)
Graphical Presentation for potential customer:
2D looks like 3D (light, shadow, transparency)
CAD Example: Pneumatic Cylinder (TurboCad 10.5)
Drawings for production by CNC

CNC stands for computer numerical control,


and refers specifically to a computer
"controller" that reads G-code instructions
and drives a machine tool
Architecture Example
(Not a photo)
Architecture & Landscape Example
(Not a photo)
Projection:
3D Real Object  2D Image on the flat screen

2D Projection on
the flat surface

3D Object

Different 2D
projections of
the same can
be created
3D Point {X,Y,Z}  2D Projection Point {Xp, Yp}
Types of 3D Projections
Rays converge on eye position Rays parallel

Perspective Parallel
Rays at angle to view plane

Rays perpendicular to view plane

Orthographic Oblique

Elevations Axonometric Cavalier Cabinet

Isometric
Parallel Projection 
Cavalier Oblique (‫ ) ֲאלַכְ סֹונִ י‬Projection
From Math to Code
(Cavalier Oblique
Projection)
Simplest Example: Cube
Set of 3D Points {X,Y,Z} to Set of 2D Projection Points {Xp, Yp}
Hidden Line and Surface Removal Algorithms:
More realistic imaging
Z-Buffer Algorithm for hidden lines/points removal
Simplest and slowest + holes possible

float zBuffer[NumOfRows][NumOfColumns];
uchar byteGrayImage [NumOfRows][NumOfColumns];

Fill zBuffer with zeroes (or with non realistic negative numbers}
Fill byteGrayImage with zeroes {or with other background value}
For each 3D point {X,Y,Z, PoinColor} calculate {Xp, Yp}
If zBuffer[Yp][Xp] < Z
{
zBuffer[Yp][Xp] = Z
byteGrayImage[Yp][Xp] = PoinColor;
}
Projection parameters: a and f
Complex 3D Objects
3D Mesh (Education: Math, CNC)
Types of Oblique Projection: Cavalier & Cabinet Projections
Small letters:
It’s time to write some code (C#, .NET)
(well explore “example”)
To work from home Download free
Microsoft Visual C# 2013 Express Edition
Steps:

• Create simplest (“Hello”) Windows Forms


application
• Create simplest 2D Drawing (Line)
• Create 3D CUBE Demo
• Add a and f controls for fun
• Improve design to beat AutoCAD…
Step 1: Creating Simplest GUI Application
with MS Visual Studio 2013 (C#)

1. Run Microsoft Visual Studio 2013


2. Main Menu: File | New | Project
Q: Why project?
A: Real software is very complex
 Many files needed to be organized
Standard approach: “project”
3. “New Project” Dialog Box appears
Fill “New Project” Dialog

1 3

5
4

8
7
6
New Project created: Main VS Elements
1. Solution (Project) Explorer:
All project files in an organized manner

2. Form
- Place for “controls”,
texts, images, etc…

4. List if standard Windows controls


like Buttons, CheckBoxes etc…
to be used in application

3. Form Properties like


“Caption”, Form Color, etc...
Refactor (Rename) “Form1” to “ImProc”:

1. Right Mouse Click


“Rename”

2. Yes,
Do Very smart rename
(refactor)
VS do a lot of work… Nearly everything is ImProc now..

1. Renaming report 2. ImProc.cs and not


(no need to read) meaningless Form1

3. Click on “Form1 and


”Type “Hello C#” here
(Mind immediate
renaming in the Form)
No line of code written ,
and full-fledged Windows Application
is created
• Press “F5”
- Standard Windows GUI Application
is created
and executed:
One can: Move, resize, minimize, close
• Standard “exe’ file is also created:
see: …/Debug/.ImProc.exe
Send this file to Your friend…
{mind problems with sending exe files}
(.Net must be installed,
- today it is “always” installed)
Step #2. Simplest 2D Drawings
Add “Control” – Panel to draw
• From “ Toolbox” drag Panel Control to the Form
• Visually stretch and position panel
• Change Back Color to “Yellow”
• (Optionally rename: Properties: Name
panel1 -> drawingPanel)
• Press “F5” to see changes

1. We will draw on this


panel
Event (Interrupt)
and Event (Interrupt) Handler
DOS/Microcontroller Application:

Start Program/Procedure
Wait for user input User “suddenly” typed
Call Function #1 “Alt-Ctrl_Del”
Call Function #2 
Wait for user input Interrupt (Stop/Halt)
Call Function #3 “normal program flow”

Return to caller Goto “specially” written function
(Event/Interrupt Handler)
Do what is written there
(for example: burn the hard disk )
Event (Interrupt)
and Event (Interrupt) Handler
Windows Application:

Start Program/Procedure Windows Events Example:


Endless Events Loop Key pressed
{ Mouse moved
Wait for Event Left Mouse button pressed
Process Event: Disk OnKey inserted to USB slot
(Call Event Handler)
}

Event Handler:
Specially Written Function

When this function executed,


Windows continue to wait for new event
Paint Event
and Paint Event Handler
The Paint event is raised when the control needs repainting

The Paint event is a CORRECT place to draw.

1. Click on drawingPanel 3. Type here name of the Event Handler


Function:
onDrawingPanelEventHandler
And double click on this name
2. Click on “Events” icon
Add Paint Event Handler: Explain events concept

1. Click here

2. Click here

3. Write friendly name here:


“onDrawingPanelPaintEventHandle
r”
and click it
It’s time to write code

Write Your code here


Code and result: Line is drawn

Basically, software developer must


remember hundreds of commands,
but even beginner can understand
what written code do
and how to change it
– nearly plain English
+ Instant Help (demonstrate)
+ Set of good examples
Great Success: We can draw now
MSDN Help: Graphics Class. Methods (functions):

DrawArc
DrawBezier
DrawClosedCurve
DrawCurve
DrawEllipse (No need for DrawCircle !!!)
DrawImage (Used in Image Processing)
DrawLine
DrawPie
DrawPolygon
DrawRectangle
DrawString

Do not forget to store this great application as (say) ImProc.DrawLine


Step #3. From 2D to 3D: Oblique Projection
3D Piramide Demo (with fixed parameters)
• Add parameters (variables)
• Write function CalculateProjection
• Write function Draw3dLine
• Modify PaintEventHandler

Download source:
…\3D Draw
Add parameters /variables : Type “Green”
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ImProc
{
public partial class ImProc : Form
{
Pen pen = new Pen(Color.Black);
float alphaInRadians = (float)Math.PI / 4;
float phiInRadians = (float)Math.PI / 6;

enum eProjectionType {Cavalier, Cabinet};


eProjectionType projectionType = eProjectionType.Cabinet;

float Xp1 = 0;
float Yp1 = 0;
float Xp2 = 0;
float Yp2 = 0;

public ImProc()
{
InitializeComponent();
}
Write function “CalculateProjection”
public Form1()
{
InitializeComponent();
}

private void CalcProjection(


float X, float Y, float Z,
ref float Xp, ref float Yp)
{
float L;
if (alphaInRadians == 0)
{
L = 0;
}
else
{
L = Z / (float) Math.Tan(alphaInRadians);
}
if (projectionType == eProjectionType.Cabinet)
{
L = L / 2;
}
Xp = (float)(X + L * (float) Math.Cos(phiInRadians));
Yp = (float)(Y - L * (float) Math.Sin(phiInRadians));

}
Write Function: “Draw3dLine”

private void Draw3DLine(Graphics gr,


float X1, float Y1, float Z1,
float X2, float Y2, float Z2)
{
CalcProjection(X1, Y1, Z1,
ref Xp1, ref Yp1);

CalcProjection(X2, Y2, Z2,


ref Xp2, ref Yp2);

gr.DrawLine(pen, Xp1, Yp1, Xp2, Yp2);


}

private void onDrawingPanelPaintEventHandler(object sender, PaintEventArgs e)


{
Modify PaintEventHandler
private void onPanelPaintEventHandler(object sender, PaintEventArgs e)
{
// Z = 0
Draw3DLine(e.Graphics,
100, 100, 0,
150, 100, 0); // Z = 50
Draw3DLine(e.Graphics, Draw3DLine(e.Graphics,
150, 100, 0, 100, 100, 50,
150, 150, 0); 150, 100, 50);
Draw3DLine(e.Graphics, Draw3DLine(e.Graphics,
150, 150, 0, 150, 100, 50,
100, 150, 0); 150, 150, 50);
Draw3DLine(e.Graphics, Draw3DLine(e.Graphics, // Connection Lines
100, 150, 0, Draw3DLine(e.Graphics,
150, 150, 50,
100, 100, 0); 100, 100, 0,
100, 150, 50);
100, 100, 50);
Draw3DLine(e.Graphics,
Draw3DLine(e.Graphics,
100, 150, 50,
150, 100, 0,
100, 100, 50);
150, 100, 50);
Draw3DLine(e.Graphics,
100, 150, 0,
100, 150, 50);
Draw3DLine(e.Graphics,
150, 150, 0,
150, 150, 50);
}
Result: 3D CUBE Demo. Oblique Projection
Cavalier versus Cabinet
Step 4. GUI: Menu, Control a and f

By Using “Properties”
Select ImProc form. Set AutoScroll True

Add “guiPanel” (BackColor: “White” )


“Adjust” form and panel sizes and locations

Options to Set Form and Panel Sizes:


“Visual” ,
By Using “Properties Panel”
Hard Coded
Professional Approach: Read from some kind of “ini file”
Add TrackBar and Labels

Drag two Label to guiPanel.


Set names as “alphaLabel” and “phiLabel”
Set text as “Alpha” and “Phi”

Drag two track bars


Set names as “alphaTrackBar” and “phiTrackBar”
In the properties set:
TickFrequency 10

Alpha Phi
Minimum 0 179
Maximum 0 360
SmallChange 1
Value 45 45
Set Location and Sizes
By Using “Properties”
Select drawingPanel
Set Location {10,10}
Set Size {640,480}

Select guiPanel
Set Location {10,500}
Set Size {640, 130}
Intermediate Appearance
(GUI do nothing for now)
Modify “constructor”

public ImProc()
{
InitializeComponent();

alphaTrackBar.Value = 45;
phiTrackBar.Value = 45;
alphaLabel.Text = "Alpha: " +
alphaTrackBar.Value.ToString();
phiLabel.Text = "Phi: " +
phiTrackBar.Value.ToString();
}
Modify “CalcProjection”
private void CalcProjection(
float X, float Y, float Z,
ref float Xp, ref float Yp)
{
float alphaInRadians =
alphaTrackBar.Value * 2 * (float)Math.PI / 360;
float phiInRadians =
phiTrackBar.Value * 2 * (float)Math.PI / 360;

float L;
if (alphaInRadians == 0)
{
L = 0;
}
else
{
L = Z / (float)Math.Tan(alphaInRadians);
}

if (projectionType == eProjectionType.Cabinet)
{
L = L / 2;
}

Xp = (float)(X + L * (float)Math.Cos(phiInRadians));
Yp = (float)(Y - L * (float)Math.Sin(phiInRadians));

}
Add Event Handlers for the Track Bars

3. Type “onAlphaTrackBarScroll”
And double click

2. Click

1. Click
Add Code for Event Handlers for the Track Bars

private void onAlphaTrackBarScroll(object sender, EventArgs e)


{
alphaLabel.Text = "Alpha: " +
alphaTrackBar.Value.ToString();
drawingPanel.Invalidate();
drawingPanel.Update();
}

private void onPhiTrackBarScroll(object sender, EventArgs e)


{
phiLabel.Text = "Phi: " +
phiTrackBar.Value.ToString();
drawingPanel.Invalidate();
drawingPanel.Update();
}
}
}
It is work now !!!

1. Standard Windows GUI:


Drag by mouse or use “Left-Right” keys

2. Numbers are updated now


It is work now !!! But HOW ???
(How event-driven software behave)
1. User scroll Alpha Track Bar
(moves by mouse or by keys – not important)

2. onAlphaTrackBarScroll event handler (function) is called:

private void onAlphaTrackBarScroll(object sender, EventArgs e)


{
alphaLabel.Text = "Alpha: " + Read current VALUE
alphaTrackBar.Value.ToString(); of the Alpha TrackBar
drawingPanel.Invalidate(); And update an Alpha Label Text
drawingPanel.Update();
}
Mark Drawing Panel as non-Valid
And update it.
Translation: Call Paint Event Handler
It is work now !!! But HOW ???
(How event-driven software behave)
private void onDrawingPanelPaintEventHandler(object
sender, PaintEventArgs e)
{
// Z = 0 Enter Paint Event Handler
Draw3DLine(e.Graphics,
100, 100, 0,
150, 100, 0);
Draw3DLine(e.Graphics,
150, 100, 0, Call Draw3DLine with XYZ[1] and XYZ[2]
150, 150, 0);
It is work now !!! But HOW ???
(How event-driven software behave)

private void Draw3DLine(Graphics gr,


float X1, float Y1, float Z1,
float X2, float Y2, float Z2)
{
CalcProjection(X1, Y1, Z1,
ref Xp1, ref Yp1);
Call CalcProjection
This is normal functions
sequence call
It is work now !!! But HOW ???
(How event-driven software behave)

At THIS MOMENT
private void CalcProjection( Request value of the track bar,
float X, float Y, float Z, Convert it and use for the
ref float Xp, ref float Yp) “calculations”
{
float alphaInRadians =
alphaTrackBar.Value * 2 * (float)Math.PI / 360;
float phiInRadians =
phiTrackBar.Value * 2 * (float)Math.PI / 360;

float L;
if (alphaInRadians == 0)
{
L = 0;
}
else
It is work now !!! But HOW ???
(How event-driven software behave)

Return to Draw3DLine
private void Draw3DLine(Graphics gr,
float X1, float Y1, float Z1,
float X2, float Y2, float Z2)
{
CalcProjection(X1, Y1, Z1,
ref Xp1, ref Yp1);
Draw on the Graphics You
CalcProjection(X2, Y2, Z2, have got from Paint
ref Xp2, ref Yp2);

gr.DrawLine(pen, Xp1, Yp1, Xp2, Yp2);


}
Return to Paint
It is work now !!! But HOW ???
(How event-driven software behave)

private void onDrawingPanelPaintEventHandler(object sender, PaintEventArgs


e)
{
// Z = 0 Return to Paint
Draw3DLine(e.Graphics,
100, 100, 0,
150, 100, 0);

Draw3DLine(e.Graphics, Draw last line


150, 150, 0,
150, 150, 50);

}
Return to Windows Event Loop and
wait for the next
UNPREDICTABLE
user’ input
Next Job to do
(Details later)

You might also like