使用 Processing 重新创建抛物线三角形 gif

如何解决使用 Processing 重新创建抛物线三角形 gif

我想使用 Processing 重新创建抛物线三角形:

parabolic triangle gif

我认为我已经弄清楚了“基本”代码。 我现在需要的是循环我的代码以获得正确数量的三角形/线。

我正在使用 n 来确定应该绘制多少个三角形,正如您所看到的,当更改 n 时,线条位置是正确的。我只需要做一个循环,以便绘制正确数量的三角形。

这是我的代码

float x1,y1,x2,y2,x3,y3;
float b,a;

float a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7,a8,b8,a9,b9;

void setup () {
  size(600,600);
  background(255);

  x2=50;
  y2=height-50;

  x3=width-50;
  y3=y2;

  b=x3-x2;
  a=b*sqrt(3)/2;

  x1=x2+b/2;
  y1=y2-a;

  stroke(255,153);
  line(x1,y2);
  stroke(0,255,253);
  line(x2,y3);
  stroke(79,144,252);
  line(x3,y3,x1,y1);
}
void draw() {
  float n=4;
  float div=(1/n);

  a1=lerp(x1,div);
  b1=lerp(y1,div);
  a2=lerp(x2,div);
  b2=lerp(y2,div);
  a3=lerp(x3,div);
  b3=lerp(y3,div);

  a4=lerp(x1,div+div);
  b4=lerp(y1,div+div);
  a5=lerp(x2,div+div);
  b5=lerp(y2,div+div);
  a6=lerp(x3,div+div);
  b6=lerp(y3,div+div);

  a7=lerp(x1,div+div+div);
  b7=lerp(y1,div+div+div);
  a8=lerp(x2,div+div+div);
  b8=lerp(y2,div+div+div);
  a9=lerp(x3,div+div+div);
  b9=lerp(y3,div+div+div);

  line(a1,b2);
  line(a2,b3);
  line(a3,a1,b1);

  line(a4,b5);
  line(a5,b6);
  line(a6,b4);

  line(a7,b8);
  line(a8,b9);
  line(a9,b9,b7);
}

解决方法

正如之前在评论中提到的,有几点需要注意:

  1. 超过必要的插值
  2. 正确映射 lerp t 参数以进行插值(代码中的 div

关于插值,您的代码当前包含此部分:

  a1=lerp(x1,x2,div);
  b1=lerp(y1,y2,div);
  a2=lerp(x2,x3,div);
  b2=lerp(y2,y3,div);
  a3=lerp(x3,x1,div);
  b3=lerp(y3,y1,div);

  a4=lerp(x1,div+div);
  b4=lerp(y1,div+div);
  a5=lerp(x2,div+div);
  b5=lerp(y2,div+div);
  a6=lerp(x3,div+div);
  b6=lerp(y3,div+div);

  a7=lerp(x1,div+div+div);
  b7=lerp(y1,div+div+div);
  a8=lerp(x2,div+div+div);
  b8=lerp(y2,div+div+div);
  a9=lerp(x3,div+div+div);
  b9=lerp(y3,div+div+div);

  line(a1,b1,a2,b2);
  line(a2,b2,a3,b3);
  line(a3,b3,a1,b1);

  line(a4,b4,a5,b5);
  line(a5,b5,a6,b6);
  line(a6,b6,a4,b4);

  line(a7,b7,a8,b8);
  line(a8,b8,a9,b9);
  line(a9,b9,a7,b7);

前 6 个插值(三角形的 3 个点之间)处理一个细分级别。使用 a1,c1,c2,c3 渲染线条应该可以解决问题。其余的插值似乎是在另一个细分级别手动插值。这是您希望通过 for 循环避免和改进的位复制/粘贴体力劳动。

关于插值参数,如果您知道细分的总数,您可以手动(使用除法)或使用 map() 函数将其映射到 t 参数

这是您的代码的修改版本,用于说明这些要点:

float x1,y3;
float b,a;

float a1,b3;

void setup () {
  frameRate(10);
  size(600,600);
  background(255);

  x2=50;
  y2=height-50;

  x3=width-50;
  y3=y2;

  b=x3-x2;
  a=b*sqrt(3)/2;

  x1=x2+b/2;
  y1=y2-a;
}

void draw() {
  background(255);
  int subdivisions = frameCount % 300;
  for(float n = 1; n < subdivisions; n++){
    float div= n / (subdivisions - 1);
  
    a1=lerp(x1,div);//x1x2
    b1=lerp(y1,div);//y1y2
    a2=lerp(x2,div);//x2x3
    b2=lerp(y2,div);//y2y3
    a3=lerp(x3,div);//x3x1
    b3=lerp(y3,div);//y3y1
    
    stroke(255,153);
    line(a1,b2);//x1x2,y1y2,x2x3,y2y3
    stroke(0,255,253);
    line(a3,b1);//x3x1,y3y1,x1x2,y1y2
    stroke(79,144,252);
    line(a2,b3);//x2x3,y2y3,x3x1,y3y1
  }
}

Parabolic Triangle Minimal Code

就我个人而言,我会将其全部封装在一个可重用的函数中(这将使其更容易在其他草图中重用)。下面是一个示例,其中我还将所有线条图一次性分组,与多个 line() 调用相反。这主要是一个偏好问题,应该会稍微加快速度,但是您永远不应该轻易牺牲可读性/灵活性。

float x1,a;

color c1 = color(255,153);
color c2 = color(0,253);
color c3 = color(79,252);

void setup () {
  size(600,600);
  background(255);

  x2 = 50;
  y2 = height - 50;

  x3 = width - 50;
  y3 = y2;

  b = x3 - x2;
  a = b * sqrt(3) / 2;

  x1 = x2 + b / 2;
  y1 = y2 - a;
}

void drawSubdivisions(int div,float x1,float y1,float x2,float y2,float x3,float y3,color c1,color c2,color c3){
  
  // alternative rendering option: render the lines in a batch
  beginShape(LINES);
    
  // for each subdivision level
  for(int i = 0; i < div; i++){
    // map the subdivision level to the t interpolation parameter
    float t = map(i,div - 1,0.0,1.0);
    // interpolate each coordinate 
    // connecting the current triangle vertex to the next 
    float x1x2 = lerp(x1,t);
    float y1y2 = lerp(y1,t);
    
    float x2x3 = lerp(x2,t);
    float y2y3 = lerp(y2,t);
    // ... and last vertex to first vertex
    float x3x1 = lerp(x3,t);
    float y3y1 = lerp(y3,t);
    
    // render lines for th interpolated shape
    
    stroke(c1);
    vertex(x1x2,y1y2); 
    vertex(x2x3,y2y3);
    
    stroke(c2);
    vertex(x2x3,y2y3); 
    vertex(x3x1,y3y1);
    
    stroke(c3);
    vertex(x3x1,y3y1);
    vertex(x1x2,y1y2);
  } 
  
  endShape();
}

void draw() {
  // map the number of subdivisions
  int subdivisions = round(map(mouseX,width,2,90));
  
  background(0);
  drawSubdivisions(subdivisions,c3);
  text("move mouse on X axis to control subdivisions: " + subdivisions,10,15);
}

Parabolic Triangle encapsulated

为了完整起见,这里有一个用 p5.js 编写的示例,您可以在下面运行。我将等边三角形概括为正多边形并使用颜色映射:

function setup() {
  createCanvas(900,900);
  colorMode(HSB,360,100,100);
}

function draw() {
  background(0,100);
  // map the number of points to Y axis
  let numPoints = round(map(mouseY,height,3,6));
  // map the number of subdivisions to the X axis 
  let subdivisions = round(map(mouseX,1,300));
  // compute regular polygon points
  let regularPolygonPoints = getRegularPolygonPoints(width * 0.5,height * 0.5,numPoints,300);
  // optional: render regular polygon points
  if(mouseIsPressed) drawPoints(regularPolygonPoints);
  // compute and render interpolation lines between pairs of points
  drawLinearInterpolation(regularPolygonPoints,subdivisions);
  // instructions:
  text(`mouseY -> numPoints:${numPoints}\nmouseX -> subdivisions: ${subdivisions}`,15);
}

// make a list of points (p5.Vector with x,y properties and conveniently lerp) 
function getRegularPolygonPoints(x,y,sides,radius){
  // output list
  let points = [];
  // calculate the angle per polygon side (same as 360 degrees / sides)
  let angleIncrement = TWO_PI / sides;
  // for each side
  for(let i = 0 ; i < sides; i++){
    // increment the angle (and offset by 90 degrees to point up)
    let angle = (angleIncrement * i) - HALF_PI; 
    // insert the points into the list
    // p5.Vector.fromAngle converts and angle radius to an x and y position (polar to cartesian)
    // we offset(add) by x,y (transalation from 0,0 to center)  
    points.push(p5.Vector.fromAngle(angle,radius).add(x,y));
  }
  // return result
  return points;
}

// draw lines between interpolated pairs of points in sequental side order
function drawLinearInterpolation(points,subdivisions){
  // make strokes thinner the more subdivisions there are
  strokeWeight((300 - subdivisions) / 600);
  let numPoints = points.length;
  beginShape(LINES);
  // for each subdivision
  for(let i = 0; i < subdivisions; i++){
    let amount    = map(i,subdivisions - 1,1.0);
    // for each point index from first to last (and back to first)
    for(let j = 0; j <= numPoints; j++){
      // array access current,previous and next points
      let current   = points[j % numPoints];
      let previous  = points[(j-1) < 0 ? numPoints - 1 : j - 1];
      let next      = points[(j+1) % numPoints];
      // interpolate between pairs of points: previous to current,current to next
      let previousToCurrent = p5.Vector.lerp(previous,current,amount);
      let currentToNext     = p5.Vector.lerp(current,next,amount);
      // play with stroke colour mapping
      stroke((mouseIsPressed ? (i + j) : (i * j)) % 360,85,100);
      // pass the point coordinates for shape rendering
      vertex(previousToCurrent.x,previousToCurrent.y);
      vertex(currentToNext.x,currentToNext.y);
    }
  }
  endShape();
}

// render a list of points
function drawPoints(points){
  strokeWeight(9);
  stroke(0,0);
  let numPoints = points.length;
  beginShape(POINTS);
  for(let i = 0 ; i < numPoints; i++){
    let point = points[i];
    vertex(point.x,point.y);
  }
  endShape();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>

Parabolic Regular Polygon (in p5.js)

您可以选择使用不同的颜色映射。 lerpColor()colorMode() 之类的函数可能很有用。玩得开心!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?