PROGRAM TABELL;
USES CRT;
VAR I, VAL:INTEGER;
STOPP:CHAR; {CHAR BETYDER CHARACTER OCH KAN VARA VILKET TECKEN SOM HELST}
BEGIN
CLRSCR;
TEXTCOLOR (LIGHTBLUE);
WRITELN('MED DETTA PROGRAM KAN DU FÅ EN GÅNGERTABELL UTSKRIVEN');
WRITELN('VILKEN TABELL ÖNSKAS?');
READLN(VAL);
FOR I:=1 TO 12 DO
BEGIN
WRITELN(I:2,' * ',VAL,' = ',I*VAL);
END;
WRITELN('TRYCK TANGENT!');
STOPP:=READKEY;
END.add(v) {
return new Vector(
this.x + v.x,
this.y + v.y);
}
addTo(v) {
this.x += v.x;
this.y += v.y;
}sub(v) {
return new Vector(
this.x - v.x,
this.y - v.y);
}
subFrom(v) {
this.x -= v.x;
this.y -= v.y;
}mult(n) {
return new Vector(
this.x * n,
this.y * n);
}
div(n) {
return new Vector(
this.x / n,
this.y / n);
}getAngle() {
return Math.atan2(
this.y,
this.x);
}
getLength() {
return Math.hypot(
this.x,
this.y);
}class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
...
}Trigonometry
Math.atan2(0, -1); // 3.14
Pythagorean theorem
Math.hypot(3, 4); // 5
import { bowyerWatson, Triangle } from 'delaunay.js';
import Vector from 'vectory-lib';
function getRandomPoints() {
let points = [];
let nrOfPoints = 10;
for(let i = 0; i < nrOfPoints; i++) {
points.push(new Vector(
Math.random() * 100,
Math.random() * 100
));
}
return points;
}
let points = getRandomPoints();
let superTriangle = new Triangle(
new Vector(-1000, 1000),
new Vector(1000, 1000),
new Vector(0, -1000)
);
let triangles = bowyerWatson(superTriangle, points);
// Do something fun with the triangles!From a consumer (caller) perspective
Each published a paper of their own in the same number of The Computer Journal, Volume 24, Number 2, May 1981
function BowyerWatson (pointList)
// pointList is a set of coordinates defining the points to be triangulated
triangulation := empty triangle mesh data structure
// must be large enough to completely contain all the points in pointList
add super-triangle to triangulation
// add all the points one at a time to the triangulation
for each point in pointList do
badTriangles := empty set
// first find all the triangles that are no longer valid due to the insertion
for each triangle in triangulation do
if point is inside circumcircle of triangle
add triangle to badTriangles
polygon := empty set
for each triangle in badTriangles do // find the boundary of the polygonal hole
for each edge in triangle do
if edge is not shared by any other triangles in badTriangles
add edge to polygon
for each triangle in badTriangles do // remove them from the data structure
remove triangle from triangulation
for each edge in polygon do // re-triangulate the polygonal hole
newTri := form a triangle from edge to point
add newTri to triangulation
for each triangle in triangulation // done inserting points, now clean up
if triangle contains a vertex from original super-triangle
remove triangle from triangulation
return triangulationimport Vector from 'vectory-lib';
export default class Triangle {
constructor(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
vertexes() {
return [this.a, this.b, this.c];
}
edges() {
return [
[this.a, this.b],
[this.b, this.c],
[this.c, this.a]
];
}
sharesAVertexWith(triangle) {
for(const v of this.vertexes()) {
for(const vv of triangle.vertexes()) {
if(v.equals(vv)) {
return true;
}
}
}
return false;
}
hasEdge(edge) {
for(const e of this.edges()) {
if(e[0].equals(edge[0]) && e[1].equals(edge[1]) ||
e[1].equals(edge[0]) && e[0].equals(edge[1])) {
return true;
}
}
return false;
}
sharesAnEdgeWith(triangle) {
for(const edge of triangle.edges()) {
if(this.hasEdge(edge)) {
return true;
}
}
return false;
}
get circumcenter() {
if(!this._circumcenter) {
let d = 2 * (this.a.x * (this.b.y - this.c.y) +
this.b.x * (this.c.y - this.a.y) +
this.c.x * (this.a.y - this.b.y));
let x = 1 / d * ((this.a.x * this.a.x + this.a.y * this.a.y) * (this.b.y - this.c.y) +
(this.b.x * this.b.x + this.b.y * this.b.y) * (this.c.y - this.a.y) +
(this.c.x * this.c.x + this.c.y * this.c.y) * (this.a.y - this.b.y));
let y = 1 / d * ((this.a.x * this.a.x + this.a.y * this.a.y) * (this.c.x - this.b.x) +
(this.b.x * this.b.x + this.b.y * this.b.y) * (this.a.x - this.c.x) +
(this.c.x * this.c.x + this.c.y * this.c.y) * (this.b.x - this.a.x));
this._circumcenter = new Vector(x, y);
}
return this._circumcenter;
}
get centroid() {
if(!this._centroid) {
this._centroid = this.a.add(this.b).add(this.c).div(3);
}
return this._centroid;
}
get circumradiusSq() {
if(!this._circumradiusSq) {
this._circumradiusSq = this.circumcenter.sub(this.a).getLengthSq();
}
return this._circumradiusSq;
}
pointIsInsideCircumcircle(point) {
let dist = point.sub(this.circumcenter).getLengthSq();
return dist < this.circumradiusSq;
}
// Methods below are not needed for Delaunay triangulation, but useful for drawing.
vertexesAsString() {
return this.vertexes().map(vertex => `${vertex.x}, ${vertex.y}`).join(", ");
}
edgeLengths() {
return this.edges().map(v => v[0].sub(v[1]).getLength());
}
heights() {
let [a, b, c] = this.edgeLengths();
function height(a, b, c) {
const s = (a + b + c) / 2;
const h = 2 * Math.sqrt(s * (s - a) * (s - b) * (s - c)) / b;
return h;
}
return [height(a, b, c), height(b, c, a), height(c, a, b)];
}
shortestHeight() {
return Math.min(...this.heights());
}
}import Triangle from './triangle.js';
export default function bowyerWatson (superTriangle, pointList) {
// pointList is a set of coordinates defining the
// points to be triangulated
let triangulation = [];
// add super-triangle to triangulation
// must be large enough to completely contain all
// the points in pointList
triangulation.push(superTriangle);
// add all the points one at a time to the triangulation
pointList.forEach(point => {
let badTriangles = [];
// first find all the triangles that are no
// longer valid due to the insertion
triangulation.forEach(triangle => {
if(triangle.pointIsInsideCircumcircle(point)) {
badTriangles.push(triangle);
}
});
let polygon = [];
// find the boundary of the polygonal hole
badTriangles.forEach(triangle => {
triangle.edges().forEach(edge => {
let edgeIsShared = badTriangles.some(otherTriangle => {
return triangle !== otherTriangle && otherTriangle.hasEdge(edge);
});
if(!edgeIsShared) {
// edge is not shared by any other
// triangles in badTriangles
polygon.push(edge);
}
});
});
// remove them from the data structure
badTriangles.forEach(triangle => {
let index = triangulation.indexOf(triangle);
if (index > -1) {
triangulation.splice(index, 1);
}
});
// re-triangulate the polygonal hole
polygon.forEach(edge => {
// form a triangle from edge to point
let newTri = new Triangle(edge[0], edge[1], point);
triangulation.push(newTri);
});
});
// done inserting points, now clean up
let i = triangulation.length;
while(i--) {
let triangle = triangulation[i];
if(triangle.sharesAVertexWith(superTriangle)) {
// remove triangle from triangulation
let index = triangulation.indexOf(triangle);
if (index > -1) {
triangulation.splice(index, 1);
}
}
}
return triangulation;
}moveTowards(v, length) {
let delta = v.sub(this).setLength(length);
return this.add(delta);
}<svg viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">
<style>
line {
stroke: black;
}
</style>
<line x1="0" y1="3" x2="30" y2="3" stroke-dasharray="4 3 2 1" />
</svg>A list of comma and/or white space separated <length>s and <percentage>s that specify the lengths of alternating dashes and gaps.
Georgy Voronoy
edges() {
return [
[this.a, this.b],
[this.b, this.c],
[this.c, this.a]
];
}
hasEdge(edge) {
for(const e of this.edges()) {
if(e[0].equals(edge[0]) && e[1].equals(edge[1]) ||
e[1].equals(edge[0]) && e[0].equals(edge[1])) {
return true;
}
}
return false;
}
sharesAnEdgeWith(triangle) {
for(const edge of triangle.edges()) {
if(this.hasEdge(edge)) {
return true;
}
}
return false;
}equals(v) {
return this.x == v.x && this.y == v.y;
}