Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
akira-cn committed Apr 11, 2020
1 parent 364ccb6 commit 242e331
Show file tree
Hide file tree
Showing 10 changed files with 1,094 additions and 0 deletions.
675 changes: 675 additions & 0 deletions common/lib/earcut.js

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions common/lib/vector2d.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ export class Vector2D extends Array {
return this;
}

sub(v) {
this.x -= v.x;
this.y -= v.y;
return this;
}

scale(a) {
this.x *= a;
this.y *= a;
Expand Down
53 changes: 53 additions & 0 deletions polygon-fill/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {Vector2D} from '../common/lib/vector2d.js';

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const {width, height} = canvas;
const w = 0.5 * width,
h = 0.5 * height;
ctx.translate(w, h);
ctx.scale(1, -1);

function draw(context, points, {
fillStyle = 'black',
close = false,
rule = 'nonzero',
} = {}) {
context.beginPath();
context.moveTo(...points[0]);
for(let i = 1; i < points.length; i++) {
context.lineTo(...points[i]);
}
if(close) context.closePath();
context.fillStyle = fillStyle;
context.fill(rule);
}

const points = [new Vector2D(0, 100)];
for(let i = 1; i <= 4; i++) {
const p = points[0].copy().rotate(i * Math.PI * 0.4);
points.push(p);
}

const polygon = [
...points,
];

ctx.save();
ctx.translate(-128, 0);
draw(ctx, polygon);
ctx.restore();

const stars = [
points[0],
points[2],
points[4],
points[1],
points[3],
];

ctx.save();
ctx.translate(128, 0);
// draw(ctx, stars);
draw(ctx, stars, {rule: 'evenodd'});
ctx.restore();
12 changes: 12 additions & 0 deletions polygon-fill/fill-canvas2d.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas2D填充</title>
</head>
<body>
<canvas width="512" height="512"></canvas>
<script type="module" src="./app.js"></script>
</body>
</html>
138 changes: 138 additions & 0 deletions triangluations/app-collision.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import {earcut} from '../common/lib/earcut.js';
import {Vector2D} from '../common/lib/vector2d.js';

function inTriangle(p1, p2, p3, point) {
const a = p2.copy().sub(p1);
const b = p3.copy().sub(p2);
const c = p1.copy().sub(p3);

const u1 = point.copy().sub(p1);
const u2 = point.copy().sub(p2);
const u3 = point.copy().sub(p3);

const s1 = Math.sign(a.cross(u1));
let p = a.dot(u1) / a.length ** 2;
if(s1 === 0 && p >= 0 && p <= 1) return true;

const s2 = Math.sign(b.cross(u2));
p = b.dot(u1) / b.length ** 2;
if(s2 === 0 && p >= 0 && p <= 1) return true;

const s3 = Math.sign(c.cross(u3));
p = c.dot(u1) / c.length ** 2;
if(s3 === 0 && p >= 0 && p <= 1) return true;

return s1 === s2 && s2 === s3;
}

function isPointInPath({vertices, cells}, point) {
let ret = false;
for(let i = 0; i < cells.length; i += 3) {
const p1 = new Vector2D(...vertices[cells[i]]);
const p2 = new Vector2D(...vertices[cells[i + 1]]);
const p3 = new Vector2D(...vertices[cells[i + 2]]);
if(inTriangle(p1, p2, p3, point)) {
ret = true;
break;
}
}
return ret;
}

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

const vertex = `
attribute vec2 position;
uniform vec4 u_color;
varying vec4 vColor;
void main() {
gl_PointSize = 1.0;
gl_Position = vec4(position, 1.0, 1.0);
vColor = u_color;
}
`;

const fragment = `
precision mediump float;
varying vec4 vColor;
void main()
{
gl_FragColor = vColor;
}
`;

const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertex);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragment);
gl.compileShader(fragmentShader);


const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

const vertices = [
[-0.7, 0.5],
[-0.4, 0.3],
[-0.25, 0.71],
[-0.1, 0.56],
[-0.1, 0.13],
[0.4, 0.21],
[0, -0.6],
[-0.3, -0.3],
[-0.6, -0.3],
[-0.45, 0.0],
];

const points = vertices.flat();
const triangles = earcut(points);
// console.log(triangles);

const position = new Float32Array(points);
const cells = new Uint16Array(triangles);

const pointBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer);
gl.bufferData(gl.ARRAY_BUFFER, position, gl.STATIC_DRAW);

const vPosition = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);

const cellsBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cellsBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, cells, gl.STATIC_DRAW);

const colorLoc = gl.getUniformLocation(program, 'u_color');
gl.uniform4fv(colorLoc, [1, 0, 0, 1]);

gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, cells.length, gl.UNSIGNED_SHORT, 0);

const {left, top} = canvas.getBoundingClientRect();
canvas.addEventListener('mousemove', (evt) => {
const {x, y} = evt;
// 坐标转换
const offsetX = 2 * (x - left) / canvas.width - 1.0;
const offsetY = 1.0 - 2 * (y - top) / canvas.height;

gl.clear(gl.COLOR_BUFFER_BIT);

const colorLoc = gl.getUniformLocation(program, 'u_color');
if(isPointInPath({vertices, cells}, new Vector2D(offsetX, offsetY))) {
gl.uniform4fv(colorLoc, [0, 0.5, 0, 1]);
} else {
gl.uniform4fv(colorLoc, [1, 0, 0, 1]);
}

gl.drawElements(gl.TRIANGLES, cells.length, gl.UNSIGNED_SHORT, 0);
});
103 changes: 103 additions & 0 deletions triangluations/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {earcut} from '../common/lib/earcut.js';

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

const vertex = `
attribute vec2 position;
void main() {
gl_PointSize = 1.0;
gl_Position = vec4(position, 1.0, 1.0);
}
`;

const fragment = `
precision mediump float;
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertex);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragment);
gl.compileShader(fragmentShader);


const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// const points = new Float32Array([
// -1, -1,
// 0, 1,
// 1, -1,
// ]);

const vertices = [
[-0.7, 0.5],
[-0.4, 0.3],
[-0.25, 0.71],
[-0.1, 0.56],
[-0.1, 0.13],
[0.4, 0.21],
[0, -0.6],
[-0.3, -0.3],
[-0.6, -0.3],
[-0.45, 0.0],
];

const points = vertices.flat();
const triangles = earcut(points);
// console.log(triangles);

const position = new Float32Array(points);
const cells = new Uint16Array(triangles);

const pointBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer);
gl.bufferData(gl.ARRAY_BUFFER, position, gl.STATIC_DRAW);

const vPosition = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);

const cellsBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cellsBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, cells, gl.STATIC_DRAW);

gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.LINE_STRIP, cells.length, gl.UNSIGNED_SHORT, 0);

// const canvas = document.querySelector('canvas');
// const ctx = canvas.getContext('2d');
// const {width, height} = canvas;
// ctx.translate(0.5 * width, 0.5 * height);
// ctx.scale(1, -1);

// const poitions = vertices.map(([x, y]) => [x * 256, y * 256]);

// function draw(points, strokeStyle = 'black', fillStyle = null) {
// ctx.strokeStyle = strokeStyle;
// ctx.beginPath();
// ctx.moveTo(...points[0]);
// for(let i = 1; i < points.length; i++) {
// ctx.lineTo(...points[i]);
// }
// ctx.closePath();
// if(fillStyle) {
// ctx.fillStyle = fillStyle;
// ctx.fill();
// }
// ctx.stroke();
// }

// draw(poitions);
71 changes: 71 additions & 0 deletions triangluations/app2d.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const vertices = [
[-0.7, 0.5],
[-0.4, 0.3],
[-0.25, 0.71],
[-0.1, 0.56],
[-0.1, 0.13],
[0.4, 0.21],
[0, -0.6],
[-0.3, -0.3],
[-0.6, -0.3],
[-0.45, 0.0],
];

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const {width, height} = canvas;
ctx.translate(0.5 * width, 0.5 * height);
ctx.scale(1, -1);

const poitions = vertices.map(([x, y]) => [x * 256, y * 256]);

function draw(ctx, points, strokeStyle = 'black', fillStyle = null) {
ctx.strokeStyle = strokeStyle;
ctx.beginPath();
ctx.moveTo(...points[0]);
for(let i = 1; i < points.length; i++) {
ctx.lineTo(...points[i]);
}
ctx.closePath();
if(fillStyle) {
ctx.fillStyle = fillStyle;
ctx.fill();
}
ctx.stroke();
}

function isPointInPath(ctx, x, y) {
const cloned = ctx.canvas.cloneNode().getContext('2d');
cloned.translate(0.5 * width, 0.5 * height);
cloned.scale(1, -1);
let ret = false;
draw(cloned, poitions, 'transparent', 'red');
ret |= cloned.isPointInPath(x, y);
if(!ret) {
draw(cloned, [[100, 100], [100, 200], [150, 200]], 'transparent', 'blue');
ret |= cloned.isPointInPath(x, y);
}
return ret;
}

draw(ctx, poitions, 'transparent', 'red');
draw(ctx, [[100, 100], [100, 200], [150, 200]], 'transparent', 'blue');

const {left, top} = canvas.getBoundingClientRect();

canvas.addEventListener('mousemove', (evt) => {
const {x, y} = evt;
// 坐标转换
const offsetX = x - left;
const offsetY = y - top;

ctx.clearRect(-256, -256, 512, 512);

if(isPointInPath(ctx, offsetX, offsetY)) {
draw(ctx, poitions, 'transparent', 'green');
draw(ctx, [[100, 100], [100, 200], [150, 200]], 'transparent', 'orange');
} else {
draw(ctx, poitions, 'transparent', 'red');
draw(ctx, [[100, 100], [100, 200], [150, 200]], 'transparent', 'blue');
}
});
Loading

0 comments on commit 242e331

Please sign in to comment.