愿所有的美好和期待都能如约而至

P5.js上每个点都有经典箭头的静态向量场

发布时间:  来源:互联网  作者:匿名  标签:error Static vector field with classic arrows at every point on p5.js exception   热度:37.5℃

本文介绍了P5.js上每个点都有经典箭头的静态向量场的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标是使用p5.js在2D或3D网格上的每个点上显示一个带有箭头的矢量场(即尖端带有人字形的线段)。原因是我看到了很多创造性的艺术使用它,而流场(?)看起来很酷,那么为什么不用它们来描述有或没有运动的物理矢量场。

我对p5.js一无所知,但快速的在线搜索显示,我可以生成从左上角开始的位置向量,以及将原点连接到其终点或从一个位置向量到另一个位置向量的线(段):

function setup() {
  createCanvas(500, 500);
}

function draw() {
  background(0);
  
  let vec1 = createVector(100,100);
  let vec2 = createVector(30,150);
  

    //First vector
      strokeWeight(10);
      stroke(250,250,250);
      line(0,0,vec1.x,vec1.y);
    
    //Second vector
      strokeWeight(10);
      stroke(250,0,250);
      line(0,0,vec2.x,vec2.y);
      
    //Difference vector
      strokeWeight(5);
      stroke(0,250,250);
      line(vec1.x,vec1.y,vec2.x,vec2.y);
    }

现在我想添加箭头,并将其美化。理想的、长期的完美将是3Blue1Brown:

推荐答案

我找到了一个答案here,例如,它允许在两点(或两个位置向量的末端)之间绘制一个向量:

function setup() {
  createCanvas(500, 500);
}


function draw() {
  background(240);

  let v0 = createVector(250,250); //Beginning point at center canvas.
  let v1 = createVector(50,50);   //Ending point at the tip of this positional vec.

  drawArrow(v0, v1, 'red'); //Function that draws a red vector from vec0 to vec1.
}


// draw an arrow for a vector at a given base position
function drawArrow(base, vec, myColor) {
  stroke(myColor);
  strokeWeight(4);
  fill(myColor);
  translate(base.x, base.y); //Will transport the object line (below) to the tip of the positional vector v1
  line(0, 0, vec.x, vec.y);  //The line from the O to the tip of v1
  rotate(vec.heading()); //Rotates the following triangle the angle of v1
  let arrowSize = 7; // Determines size of the vector arrowhead (triangle).
  translate(vec.mag() - arrowSize, 0); //Will translate a triangle below by the modulus of v1
  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
}

或此处是从画布中心到鼠标尖端的矢量:

function setup() {
  createCanvas(500, 500);
}


function draw() {
  background(240);

  let v0 = createVector(250,250);
  let v1 = createVector(mouseX - 250, mouseY - 250);

  drawArrow(v0, v1, 'red');
}


// draw an arrow for a vector at a given base position
function drawArrow(base, vec, myColor) {
  stroke(myColor);
  strokeWeight(4);
  fill(myColor);
  translate(base.x, base.y);
  line(0, 0, vec.x, vec.y);
  rotate(vec.heading());
  let arrowSize = 7;
  translate(vec.mag() - arrowSize, 0);
  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
}

这里不只是一个向量,而是用上面的代码创建的实际(随机)向量场,调整了Daniel Shiffman的行here:

var inc = 0.1;
scl = 35;
var cols,rows;

function setup() {
  createCanvas(500,500);
  cols = floor(width/scl);
  rows = floor(height/scl);
  }



function draw() {
  background(255);
  var yoff = 0;
  loadPixels();
  for (var y = 0; y < rows; y++) {
    var xoff = 0;
    for (var x = 0; x < cols; x++) {
      var index = (x + y * width)*4;
      var angle = noise(xoff,yoff) * TWO_PI;
      var v = p5.Vector.fromAngle(angle);
      xoff +- inc;
      fill('blue');
      stroke('blue');
      push();
      translate(x*scl,y*scl);
      rotate(v.heading());
      line(0,0,0.5*scl,0);
      let arrowSize = 7;
      translate(0.5*scl - arrowSize, 0);
      triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
      pop();
    }
    yoff += inc;
  }
}

遗憾的是,左上角的原点使得用数学方式表示的物理场相当误导,传达了场逆时针流动的直觉:

var inc = 0.1;
scl = 35;
var cols,rows;

function setup() {
  createCanvas(500,500);
  cols = floor(width/scl);
  rows = floor(height/scl);
  }



function draw() {
  background(255);
  var yoff = 0;
  loadPixels();
  for (var y = 0; y < rows; y++) {
    var xoff = 0;
    for (var x = 0; x < cols; x++) {
      var index = (x + y * width)*4;
      var angle = noise(xoff,yoff) * TWO_PI;
      //var v = createVector(sin(x)+cos(y),sin(x)*cos(y));
      var v = createVector(y,-x);
      xoff +- inc;
      fill('blue');
      stroke('blue');
      push();
      translate(x*scl,y*scl);
      rotate(v.heading());
      line(0,0,0.5*scl,0);
      let arrowSize = 7;
      translate(0.5*scl - arrowSize, 0);
      triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
      pop();
    }
    yoff += inc;
  }
}

最常见的具有负值和正值以及四个象限的笛卡尔坐标将显示该场实际上是如何顺时针流动的:

但这似乎有一个几乎很简单的修复方法,将计数器重置为从减去行数(和列数)到加上行数(和列数),而不是从零开始。此外,需要在y轴上反转递增值的方向,原点需要平移到画布的中间(height/2,height/2)如果是方形的:

var inc = 0.1;
scl = 35;
var cols,rows;

function setup() {
  createCanvas(500,500);
  cols = floor(width/scl);
  rows = floor(height/scl);
  }



function draw() {
  translate(height/2, height/2);  //moves the origin to bottom left
  scale(1, -1);  //flips the y values so y increases "up"
  background(255);
  var yoff = 0;
  loadPixels();
  for (var y = -rows; y < rows; y++) {
    var xoff = 0;
    for (var x =- cols; x < cols; x++) {
      var index = (x + y * width)*4;
      var angle = noise(xoff,yoff) * TWO_PI;
      //var v = createVector(sin(x)+cos(y),sin(x)*cos(y));
      var v = createVector(y,-x);
      xoff +- inc;
      fill('blue');
      stroke('blue');
      push();
      translate(x*scl,y*scl);
      rotate(v.heading());
      line(0,0,0.5*scl,0);
      let arrowSize = 7;
      translate(0.5*scl - arrowSize, 0);
      triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
      pop();
    }
    yoff += inc;
  }
}

这篇关于P5.js上每个点都有经典箭头的静态向量场的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,

勇敢去编程!

勇敢的热爱编程,未来的你一定会大放异彩,未来的生活一定会因编程更好!

TOP