增加一篇博客
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.2/lib/p5.js"></script>
|
||||
<script src="/js/bezier_app.js"></script>
|
||||
<script src="/js/bezier_base.js"></script>
|
||||
</head>
|
||||
<body style="margin:0px; padding:0px; overflow: hidden">
|
||||
<script>
|
||||
|
||||
var lineSegments;
|
||||
var quadBezierLine;
|
||||
var P0={x:10.0, y:10.0}, P1={x:260.0, y:235.0}, P2={x:300.0, y:80.0};
|
||||
|
||||
function setup() {
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
let uniformSpeed = searchParams.get('uniformSpeed')!=0;
|
||||
|
||||
canvas = createCanvas(windowWidth, windowHeight);
|
||||
|
||||
lineSegments = new LineSegments();
|
||||
lineSegments.addPoint(P0.x, P0.y);
|
||||
lineSegments.addPoint(P1.x, P1.y);
|
||||
lineSegments.addPoint(P2.x, P2.y);
|
||||
|
||||
quadBezierLine = new QuadBezierLine(P0, P1, P2, 20, uniformSpeed)
|
||||
}
|
||||
|
||||
function draw() {
|
||||
clear();
|
||||
background('white');
|
||||
noStroke();
|
||||
|
||||
lineSegments.draw();
|
||||
quadBezierLine.draw()
|
||||
}
|
||||
|
||||
function mousePressed(){
|
||||
lineSegments.handleMousePressed();
|
||||
}
|
||||
|
||||
function mouseDragged(){
|
||||
lineSegments.handleMouseDragged();
|
||||
}
|
||||
|
||||
function mouseReleased(){
|
||||
lineSegments.handleMouseReleased();
|
||||
quadBezierLine.updatePoints(lineSegments.points[0], lineSegments.points[1], lineSegments.points[2]);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
@@ -0,0 +1,78 @@
|
||||
class QuadBezierLine {
|
||||
constructor(_p0, _p1, _p2, _step, _uniformSpeed) {
|
||||
this.step=_step;
|
||||
this.points=[];
|
||||
this.uniformSpeed=_uniformSpeed;
|
||||
this.updatePoints(_p0, _p1, _p2);
|
||||
}
|
||||
|
||||
//Speed(t_) = Sqrt[A*t*t+B*t+C]
|
||||
speed(t) {
|
||||
return Math.sqrt(this.A * t * t + this.B * t + this.C);
|
||||
}
|
||||
|
||||
//Length(t) = Integrate[Speed[t], t]
|
||||
//Length(t_)=((2*Sqrt[A]*(2*A*t*Sqrt[C+t*(B+A*t)]+B*(Sqrt[C + t*(B + A*t)]-Sqrt[C])) +
|
||||
// (B^2-4*A*C)(Log[B+2*Sqrt[A]*Sqrt[C]]-Log[B+2*A*t+2*Sqrt[A]*Sqrt[C+t*(B+A*t)]]))/
|
||||
// (8* A^(3/2)));
|
||||
length(t) {
|
||||
let temp1 = Math.sqrt(this.C + t * (this.B + this.A * t));
|
||||
let temp2 = (2 * this.A * t * temp1 + this.B * (temp1 - Math.sqrt(this.C)));
|
||||
let temp3 = Math.log(this.B + 2 * Math.sqrt(this.A) * Math.sqrt(this.C));
|
||||
let temp4 = Math.log(this.B + 2 * this.A * t + 2 * Math.sqrt(this.A) * temp1);
|
||||
let temp5 = 2 * Math.sqrt(this.A) * temp2;
|
||||
let temp6 = (this.B * this.B - 4 * this.A * this.C) * (temp3 - temp4);
|
||||
return (temp5 + temp6) / (8 * Math.pow(this.A, 1.5));
|
||||
}
|
||||
|
||||
//X(n+1) = Xn - F(Xn)/F'(Xn)
|
||||
invertLength(t, len) {
|
||||
let t1 = t, t2;
|
||||
do {
|
||||
t2 = t1 - (this.length(t1) - len) / this.speed(t1);
|
||||
if (Math.abs(t1 - t2) < 0.000001)
|
||||
break;
|
||||
t1 = t2;
|
||||
} while (true);
|
||||
return t2;
|
||||
}
|
||||
|
||||
updatePoints(_p0, _p1, _p2) {
|
||||
this.p0=_p0;
|
||||
this.p1=_p1;
|
||||
this.p2=_p2;
|
||||
|
||||
let ax = this.p0.x - 2 * this.p1.x + this.p2.x;
|
||||
let ay = this.p0.y - 2 * this.p1.y + this.p2.y;
|
||||
let bx = 2 * this.p1.x - 2 * this.p0.x;
|
||||
let by = 2 * this.p1.y - 2 * this.p0.y;
|
||||
|
||||
this.A = 4 * (ax * ax + ay *ay);
|
||||
this.B = 4 * (ax * bx + ay *by);
|
||||
this.C = bx * bx + by * by;
|
||||
|
||||
this.points.length = 0;
|
||||
let totalLength = this.length(1);
|
||||
|
||||
for (let index = 1; index < this.step; index++) {
|
||||
let t = index / this.step;
|
||||
|
||||
if(this.uniformSpeed) {
|
||||
//根据 L 函数的反函数,求得 l 对应的 t 值
|
||||
t = this.invertLength(t, totalLength*t);
|
||||
}
|
||||
|
||||
let x = (1-t)*(1-t)*this.p0.x+2*(1-t)*t*this.p1.x+t*t*this.p2.x;
|
||||
let y = (1-t)*(1-t)*this.p0.y+2*(1-t)*t*this.p1.y+t*t*this.p2.y;
|
||||
|
||||
this.points.push({x:x, y:y});
|
||||
}
|
||||
}
|
||||
|
||||
draw() {
|
||||
this.points.forEach(pt => {
|
||||
fill('green');
|
||||
ellipse(pt.x, pt.y, 5, 5);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
|
||||
class Point {
|
||||
constructor(x, y){
|
||||
this.pos = createVector(x, y);
|
||||
this.radius = 10;
|
||||
this.isDragged = false;
|
||||
this.isBeingDragged = false;
|
||||
}
|
||||
|
||||
get x(){ return this.pos.x; }
|
||||
get y(){ return this.pos.y; }
|
||||
set x(newVal){ this.pos.x = newVal; }
|
||||
set y(newVal){ this.pos.y = newVal; }
|
||||
set(x, y){ this.x = x; this.y = y; }
|
||||
|
||||
containsXY(x, y){
|
||||
return dist(x, y, this.x, this.y) < this.radius;
|
||||
}
|
||||
|
||||
handleMousePressed(){
|
||||
this.isDragged = this.containsXY(mouseX, mouseY);
|
||||
return this.isDragged;
|
||||
}
|
||||
|
||||
handleMouseDragged(){
|
||||
this.set(mouseX, mouseY);
|
||||
}
|
||||
|
||||
handleMouseReleased(){
|
||||
this.isDragged = false;
|
||||
}
|
||||
|
||||
draw(){
|
||||
if (this.containsXY(mouseX, mouseY)){
|
||||
fill('red');
|
||||
}else {
|
||||
fill('gray');
|
||||
}
|
||||
stroke('black')
|
||||
ellipse(this.x, this.y, this.radius, this.radius);
|
||||
}
|
||||
}
|
||||
|
||||
class LineSegments {
|
||||
constructor() {
|
||||
this.points = [];
|
||||
}
|
||||
|
||||
addPoint(x,y) {
|
||||
this.points.push(new Point(x, y));
|
||||
}
|
||||
|
||||
draw(){
|
||||
stroke('black')
|
||||
if(this.points.length>1) {
|
||||
for(let index=0; index<this.points.length-1; index++) {
|
||||
line(this.points[index].x, this.points[index].y, this.points[index+1].x, this.points[index+1].y);
|
||||
}
|
||||
this.points.forEach(pt => pt.draw())
|
||||
}
|
||||
}
|
||||
|
||||
handleMousePressed(){
|
||||
const pointPressed = this.points.find(pt => pt.containsXY(mouseX, mouseY));
|
||||
if (pointPressed){
|
||||
pointPressed.isBeingDragged = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
handleMouseDragged(){
|
||||
const pointDragged = this.points.find(p => p.isBeingDragged);
|
||||
if (pointDragged) {
|
||||
pointDragged.set(mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseReleased(){
|
||||
this.points.forEach(p => { p.isBeingDragged = false; });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user