fdai7303
2 years ago
12 changed files with 477 additions and 0 deletions
-
43dist/bresenham.html
-
43dist/bresenhamsimple.html
-
42dist/dda.html
-
42dist/ddasimple.html
-
13src/04/bresenham.ts
-
24src/04/bresenhamsimple.ts
-
31src/04/dda.ts
-
28src/04/ddasimple.ts
-
64src/04/setup-bresenham.ts
-
40src/04/setup-bresenhamsimple.ts
-
68src/04/setup-dda.ts
-
39src/04/setup-ddasimple.ts
@ -0,0 +1,43 @@ |
|||||
|
|
||||
|
<!DOCTYPE html> |
||||
|
|
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Graphische Datenverarbeitung - 2D - Bresenham</title> |
||||
|
<script type="text/javascript" src="bresenham.bundle.js"></script> |
||||
|
<link rel="icon" type="image/png" href="ai-logo.png"> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar navbar-light bg-light"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/index.html"> |
||||
|
<img src="ai-logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> |
||||
|
Graphische Datenverarbeitung |
||||
|
</a> |
||||
|
<div class="navbar-brand">Bresenham</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="result" class="figure-img mx-auto d-block" width="300" height="300"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Implement the Bresenham algorithm to create a rotating line |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
<figure class="col-sm-6 figure"> |
||||
|
<canvas id="original" class="figure-img mx-auto d-block" width="300" height="300"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Reference image. The reference uses the build-in line drawing functionality |
||||
|
and is smoothed. Your line will look a bit more jagged. |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -0,0 +1,43 @@ |
|||||
|
|
||||
|
<!DOCTYPE html> |
||||
|
|
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Graphische Datenverarbeitung - 2D - Bresenham</title> |
||||
|
<script type="text/javascript" src="bresenhamsimple.bundle.js"></script> |
||||
|
<link rel="icon" type="image/png" href="ai-logo.png"> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar navbar-light bg-light"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/index.html"> |
||||
|
<img src="ai-logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> |
||||
|
Graphische Datenverarbeitung |
||||
|
</a> |
||||
|
<div class="navbar-brand">Simple Bresenham</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="result" class="figure-img mx-auto d-block" width="300" height="300"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Implement the Bresenham algorithm to create a single line |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
<figure class="col-sm-6 figure"> |
||||
|
<canvas id="original" class="figure-img mx-auto d-block" width="300" height="300"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Reference image. The reference uses the build-in line drawing functionality |
||||
|
and is smoothed. Your line will look a bit more jagged. |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -0,0 +1,42 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
|
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Graphische Datenverarbeitung - 2D - DDA</title> |
||||
|
<link rel="icon" type="image/png" href="ai-logo.png"> |
||||
|
<script type="text/javascript" src="dda.bundle.js"></script> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar navbar-light bg-light"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/index.html"> |
||||
|
<img src="ai-logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> |
||||
|
Graphische Datenverarbeitung |
||||
|
</a> |
||||
|
<div class="navbar-brand">DDA</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="result" class="figure-img mx-auto d-block" width="300" height="300"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Implement the DDA algorithm to create a rotating line |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
<figure class="col-sm-6 figure"> |
||||
|
<canvas id="original" class="figure-img mx-auto d-block" width="300" height="300"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Reference image. The reference uses the build-in line drawing functionality |
||||
|
and is smoothed. Your line will look a bit more jagged. |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -0,0 +1,42 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
|
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Graphische Datenverarbeitung - 2D - Simple DDA</title> |
||||
|
<link rel="icon" type="image/png" href="ai-logo.png"> |
||||
|
<script type="text/javascript" src="ddasimple.bundle.js"></script> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar navbar-light bg-light"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/index.html"> |
||||
|
<img src="ai-logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> |
||||
|
Graphische Datenverarbeitung |
||||
|
</a> |
||||
|
<div class="navbar-brand">Simple DDA</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="result" class="figure-img mx-auto d-block" width="300" height="300"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Implement the DDA algorithm to create an single line |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
<figure class="col-sm-6 figure"> |
||||
|
<canvas id="original" class="figure-img mx-auto d-block" width="300" height="300"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Reference image. The reference uses the build-in line drawing functionality |
||||
|
and is smoothed. Your line will look a bit more jagged. |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -0,0 +1,13 @@ |
|||||
|
/** |
||||
|
* Draws a line from pointA to pointB on the canvas |
||||
|
* with the Bresenham algorithm. |
||||
|
* @param {Uint8ClampedArray} data - The linearised pixel array |
||||
|
* @param {[number, number]} pointA - The start point of the line |
||||
|
* @param {[number, number]} pointB - The end point of the line |
||||
|
* @param {number} width - The width of the canvas |
||||
|
* @param {number} height - The height of the canvas |
||||
|
*/ |
||||
|
export function bresenham(data: Uint8ClampedArray, pointA: [number, number], pointB: [number, number], width: number, height: number) { |
||||
|
|
||||
|
// TODO: Adapt the C-implementation at https://de.wikipedia.org/wiki/Bresenham-Algorithmus#C-Implementierung
|
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
function setPixel(data: Uint8ClampedArray, x: number, y: number, width: number, height: number) { |
||||
|
|
||||
|
var index = (x + y * width) * 4; |
||||
|
data[index + 0] = 0; |
||||
|
data[index + 1] = 0; |
||||
|
data[index + 2] = 0; |
||||
|
data[index + 3] = 255; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Draws a line from pointA to pointB on the canvas |
||||
|
* with the Bresenham algorithm. |
||||
|
* @param {Uint8ClampedArray} data - The linearised pixel array |
||||
|
* @param {[number, number]} pointA - The start point of the line |
||||
|
* @param {[number, number]} pointB - The end point of the line |
||||
|
* @param {number} width - The width of the canvas |
||||
|
* @param {number} height - The height of the canvas |
||||
|
*/ |
||||
|
export function bresenhamSimple(data: Uint8ClampedArray, pointA: [number, number], pointB: [number, number], width: number, height: number) { |
||||
|
|
||||
|
// TODO: 1. Calculate dx and dy and set the start position x and y
|
||||
|
// TODO: 2. Calculate the initial epsilon of the bresenham algorithm
|
||||
|
// TODO: 3. Go from pointA[0] to pointB[0], and update epsilon in each step as given in the bresenham algorithm. Increase y when necessary.
|
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
/** |
||||
|
* Draws a line from pointA to pointB on the canvas |
||||
|
* with the DDA algorithm. |
||||
|
* @param {Array.<number>} data - The linearised pixel array |
||||
|
* @param {Array.<number>} pointA - The start point of the line |
||||
|
* @param {Array.<number>} pointB - The end point of the line |
||||
|
* @param {number} width - The width of the canvas |
||||
|
* @param {number} height - The height of the canvas |
||||
|
*/ |
||||
|
export function dda( |
||||
|
data: Uint8ClampedArray, |
||||
|
pointA: [number, number], |
||||
|
pointB: [number, number], |
||||
|
width: number, height: number |
||||
|
) { |
||||
|
let setPixel = function ( |
||||
|
x: number, y: number, |
||||
|
data: Uint8ClampedArray, width: number |
||||
|
) { |
||||
|
data[4 * (width * y + x) + 0] = 0; |
||||
|
data[4 * (width * y + x) + 1] = 0; |
||||
|
data[4 * (width * y + x) + 2] = 0; |
||||
|
data[4 * (width * y + x) + 3] = 255; |
||||
|
} |
||||
|
|
||||
|
setPixel(pointA[0], pointA[1], data, width); |
||||
|
setPixel(pointB[0], pointB[1], data, width); |
||||
|
|
||||
|
// TODO: Distinguish between the main direction x and y.
|
||||
|
// TODO: Swap start and end points if necessary to reduce the number of cases.
|
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
function setPixel(data: Uint8ClampedArray, x: number, y: number, width: number, height: number) { |
||||
|
|
||||
|
var index = (x + y * width) * 4; |
||||
|
data[index + 0] = 0; |
||||
|
data[index + 1] = 0; |
||||
|
data[index + 2] = 0; |
||||
|
data[index + 3] = 255; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Draws a line from pointA to pointB on the canvas |
||||
|
* with the DDA algorithm. |
||||
|
* @param {Array.<number>} data - The linearised pixel array |
||||
|
* @param {Array.<number>} pointA - The start point of the line |
||||
|
* @param {Array.<number>} pointB - The end point of the line |
||||
|
* @param {number} width - The width of the canvas |
||||
|
* @param {number} height - The height of the canvas |
||||
|
*/ |
||||
|
export function ddaSimple( |
||||
|
data: Uint8ClampedArray, |
||||
|
pointA: [number, number], |
||||
|
pointB: [number, number], |
||||
|
width: number, height: number |
||||
|
) { |
||||
|
// TODO: Calculcate the slope m for a line from pointA to pointB.
|
||||
|
// TODO: In this example, the main direction of the line is the x-direction.
|
||||
|
// TODO: Go from the x-coordinate of pointA (pointA[0]) to the x-coordinate of pointB (pointB[0]) and calculate the y-coordinate of the pixels in between.
|
||||
|
} |
@ -0,0 +1,64 @@ |
|||||
|
|
||||
|
import 'bootstrap'; |
||||
|
import 'bootstrap/scss/bootstrap.scss'; |
||||
|
import { bresenham } from './bresenham'; |
||||
|
|
||||
|
let canvasExample: HTMLCanvasElement; |
||||
|
let ctxExample: CanvasRenderingContext2D; |
||||
|
|
||||
|
function updateExample(pointA: [number, number], pointB: [number, number]) { |
||||
|
ctxExample.clearRect(0, 0, canvasExample.width, canvasExample.height); |
||||
|
ctxExample.beginPath(); |
||||
|
ctxExample.moveTo(pointA[0], pointA[1]); |
||||
|
ctxExample.lineTo(pointB[0], pointB[1]); |
||||
|
ctxExample.stroke(); |
||||
|
} |
||||
|
|
||||
|
let canvasBresenham: HTMLCanvasElement; |
||||
|
let ctxBresenham: CanvasRenderingContext2D; |
||||
|
let imageDataBresenham: ImageData; |
||||
|
|
||||
|
function updateBresenham(pointA: [number, number], pointB: [number, number]) { |
||||
|
const data = imageDataBresenham.data; |
||||
|
data.fill(0); |
||||
|
bresenham(data, pointA, pointB, canvasBresenham.width, canvasBresenham.height); |
||||
|
ctxBresenham.putImageData(imageDataBresenham, 0, 0); |
||||
|
} |
||||
|
|
||||
|
let t = 0; |
||||
|
|
||||
|
function calculatePoints(t: number): [[number, number], [number, number]] { |
||||
|
const pointA = [ |
||||
|
Math.round((Math.cos(t) + 1) / 2 * canvasBresenham.width), |
||||
|
Math.round((Math.sin(t) + 1) / 2 * canvasBresenham.height) |
||||
|
] as [number, number]; |
||||
|
const pointB = [ |
||||
|
Math.round((Math.cos(t + Math.PI) + 1) / 2 * canvasBresenham.width), |
||||
|
Math.round((Math.sin(t + Math.PI) + 1) / 2 * canvasBresenham.height) |
||||
|
] as [number, number]; |
||||
|
return [pointA, pointB]; |
||||
|
} |
||||
|
|
||||
|
function updateCanvas(timestamp: number) { |
||||
|
t += 0.01; |
||||
|
const points = calculatePoints(t); |
||||
|
updateExample(points[0], points[1]); |
||||
|
updateBresenham(points[0], points[1]); |
||||
|
window.requestAnimationFrame(updateCanvas); |
||||
|
} |
||||
|
|
||||
|
window.addEventListener('load', evt => { |
||||
|
canvasBresenham = document.getElementById("result") as HTMLCanvasElement; |
||||
|
if (canvasBresenham === null) |
||||
|
return; |
||||
|
canvasBresenham.height = canvasBresenham.width; |
||||
|
ctxBresenham = canvasBresenham.getContext("2d"); |
||||
|
imageDataBresenham = ctxBresenham.getImageData( |
||||
|
0, 0, canvasBresenham.width, canvasBresenham.height); |
||||
|
|
||||
|
canvasExample = document.getElementById("original") as HTMLCanvasElement; |
||||
|
canvasExample.height = canvasExample.width; |
||||
|
ctxExample = canvasExample.getContext("2d"); |
||||
|
|
||||
|
window.requestAnimationFrame(updateCanvas); |
||||
|
}); |
@ -0,0 +1,40 @@ |
|||||
|
import 'bootstrap'; |
||||
|
import 'bootstrap/scss/bootstrap.scss'; |
||||
|
import { bresenhamSimple } from './bresenhamsimple'; |
||||
|
|
||||
|
var pointA: [ number, number ] = [ 0, 0 ]; |
||||
|
var pointB: [ number, number ] = [ 200, 100 ]; |
||||
|
|
||||
|
let canvasBresenham: HTMLCanvasElement; |
||||
|
let ctxBresenham: CanvasRenderingContext2D; |
||||
|
let imageDataBresenham: ImageData; |
||||
|
|
||||
|
function drawBresenham() { |
||||
|
|
||||
|
const data = imageDataBresenham.data; |
||||
|
data.fill(0); |
||||
|
bresenhamSimple(data, pointA, pointB, canvasBresenham.width, canvasBresenham.height); |
||||
|
ctxBresenham.putImageData(imageDataBresenham, 0, 0); |
||||
|
} |
||||
|
|
||||
|
window.addEventListener('load', evt => { |
||||
|
|
||||
|
canvasBresenham = document.getElementById("result") as HTMLCanvasElement; |
||||
|
if (canvasBresenham === null) |
||||
|
return; |
||||
|
|
||||
|
ctxBresenham = canvasBresenham.getContext("2d"); |
||||
|
imageDataBresenham = ctxBresenham.getImageData(0, 0, canvasBresenham.width, canvasBresenham.height); |
||||
|
|
||||
|
const canvasExample = document.getElementById("original") as HTMLCanvasElement; |
||||
|
canvasExample.height = canvasExample.width; |
||||
|
const ctxExample = canvasExample.getContext("2d"); |
||||
|
|
||||
|
ctxExample.clearRect(0, 0, canvasExample.width, canvasExample.height); |
||||
|
ctxExample.beginPath(); |
||||
|
ctxExample.moveTo(pointA[0], pointA[1]); |
||||
|
ctxExample.lineTo(pointB[0], pointB[1]); |
||||
|
ctxExample.stroke(); |
||||
|
|
||||
|
drawBresenham(); |
||||
|
}); |
@ -0,0 +1,68 @@ |
|||||
|
|
||||
|
import 'bootstrap'; |
||||
|
import 'bootstrap/scss/bootstrap.scss'; |
||||
|
import { dda } from './dda'; |
||||
|
|
||||
|
let canvasDDA: HTMLCanvasElement; |
||||
|
let ctxDDA: CanvasRenderingContext2D; |
||||
|
let imageDataDDA: ImageData; |
||||
|
|
||||
|
function updateDDA( |
||||
|
pointA: [number, number], |
||||
|
pointB: [number, number] |
||||
|
) { |
||||
|
const data = imageDataDDA.data; |
||||
|
data.fill(0); |
||||
|
dda(data, pointA, pointB, canvasDDA.width, canvasDDA.height); |
||||
|
ctxDDA.putImageData(imageDataDDA, 0, 0); |
||||
|
} |
||||
|
|
||||
|
let canvasExample: HTMLCanvasElement; |
||||
|
let ctxExample: CanvasRenderingContext2D; |
||||
|
|
||||
|
function updateExample( |
||||
|
pointA: [number, number], |
||||
|
pointB: [number, number] |
||||
|
) { |
||||
|
ctxExample.clearRect(0, 0, canvasExample.width, canvasExample.height); |
||||
|
ctxExample.beginPath(); |
||||
|
ctxExample.moveTo(pointA[0], pointA[1]); |
||||
|
ctxExample.lineTo(pointB[0], pointB[1]); |
||||
|
ctxExample.stroke(); |
||||
|
} |
||||
|
|
||||
|
let t = 0; |
||||
|
|
||||
|
function calculatePoints(t: number): [[number, number], [number, number]] { |
||||
|
const pointA = [ |
||||
|
Math.round((Math.cos(t) + 1) / 2 * canvasDDA.width), |
||||
|
Math.round((Math.sin(t) + 1) / 2 * canvasDDA.height) |
||||
|
] as [number, number]; |
||||
|
const pointB = [ |
||||
|
Math.round((Math.cos(t + Math.PI) + 1) / 2 * canvasDDA.width), |
||||
|
Math.round((Math.sin(t + Math.PI) + 1) / 2 * canvasDDA.height) |
||||
|
] as [number, number]; |
||||
|
return [pointA, pointB]; |
||||
|
} |
||||
|
|
||||
|
function updateCanvas(timestamp: number) { |
||||
|
t += 0.01; |
||||
|
const points = calculatePoints(t); |
||||
|
updateExample(points[0], points[1]); |
||||
|
updateDDA(points[0], points[1]); |
||||
|
window.requestAnimationFrame(updateCanvas); |
||||
|
} |
||||
|
|
||||
|
window.addEventListener('load', evt => { |
||||
|
canvasDDA = document.getElementById("result") as HTMLCanvasElement; |
||||
|
if (canvasDDA === null) |
||||
|
return; |
||||
|
ctxDDA = canvasDDA.getContext("2d"); |
||||
|
imageDataDDA = ctxDDA.getImageData(0, 0, canvasDDA.width, canvasDDA.height); |
||||
|
|
||||
|
canvasExample = document.getElementById("original") as HTMLCanvasElement; |
||||
|
canvasExample.height = canvasExample.width; |
||||
|
ctxExample = canvasExample.getContext("2d"); |
||||
|
|
||||
|
window.requestAnimationFrame(updateCanvas); |
||||
|
}); |
@ -0,0 +1,39 @@ |
|||||
|
import 'bootstrap'; |
||||
|
import 'bootstrap/scss/bootstrap.scss'; |
||||
|
import { ddaSimple } from './ddasimple'; |
||||
|
|
||||
|
var pointA: [ number, number ] = [ 0, 0 ]; |
||||
|
var pointB: [ number, number ] = [ 200, 100 ]; |
||||
|
|
||||
|
let canvasDDA: HTMLCanvasElement; |
||||
|
let ctxDDA: CanvasRenderingContext2D; |
||||
|
let imageDataDDA: ImageData; |
||||
|
|
||||
|
function drawDDA() { |
||||
|
|
||||
|
const data = imageDataDDA.data; |
||||
|
data.fill(0); |
||||
|
ddaSimple(data, pointA, pointB, canvasDDA.width, canvasDDA.height); |
||||
|
ctxDDA.putImageData(imageDataDDA, 0, 0); |
||||
|
} |
||||
|
|
||||
|
window.addEventListener('load', evt => { |
||||
|
|
||||
|
canvasDDA = document.getElementById("result") as HTMLCanvasElement; |
||||
|
if (canvasDDA === null) |
||||
|
return; |
||||
|
ctxDDA = canvasDDA.getContext("2d"); |
||||
|
imageDataDDA = ctxDDA.getImageData(0, 0, canvasDDA.width, canvasDDA.height); |
||||
|
|
||||
|
const canvasExample = document.getElementById("original") as HTMLCanvasElement; |
||||
|
canvasExample.height = canvasExample.width; |
||||
|
const ctxExample = canvasExample.getContext("2d"); |
||||
|
|
||||
|
ctxExample.clearRect(0, 0, canvasExample.width, canvasExample.height); |
||||
|
ctxExample.beginPath(); |
||||
|
ctxExample.moveTo(pointA[0], pointA[1]); |
||||
|
ctxExample.lineTo(pointB[0], pointB[1]); |
||||
|
ctxExample.stroke(); |
||||
|
|
||||
|
drawDDA(); |
||||
|
}); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue