如何在现有曲线p5.js上的两个贝塞尔点之间绘制重叠曲线

问题描述 投票:1回答:3

我正在使用p5.js绘制贝塞尔曲线。我想用另一种颜色绘制一条较短的,部分重叠的曲线。基本上,我想在某些地方改变曲线的颜色。我能够绘制第一条曲线并从曲线中得到两个贝塞尔点,但我无法弄清楚用于新(较小)曲线的控制点。

bezier(x1,y1,cpx1,cpy1,cpx2,cpy2,x2,y2)
AX = x1
BX = cpx1
CX = cpx2
DX = x2

AY = y1
BY = cpy1
CY = cpy2
DY = y2

let t = 0.68;
let ncX = bezierPoint(AX, BX, CX, DX, t);
let ncY = bezierPoint(AY, BY, CY, DY, t);

let t1 = 0.93;
let ncX1 = bezierPoint(AX, BX, CX, DX, t1);
let ncY1 = bezierPoint(AY, BY, CY, DY, t1);

bezier(ncX,ncY,BX,BY,CX,CY,ncX1,ncY1)
//I tried using the original curve control points, but that didn't work
processing p5.js
3个回答
0
投票

你需要的只是P5.bezier(),P5.bezierPoint()和一些绘图功能(点,椭圆)(点击画布绘制颜色)。

let	x1 = 500,
	y1 = 250,
	x2 = 0,
	y2 = 125,
	x3 = 0,
	y3 = 125,
	x4 = 500,
	y4 = 0;

let steps = 1000,       //variables needed for color change
    cStep = 250/steps,
    c = cStep;

let clicked = false;
  
function setup(){
	var canvas = createCanvas(500, 250);
	noLoop();
}

function draw(){
	background(50, 50, 100);
	noFill();
	stroke(255);
	bezier(x1, y1, x2, y2, x3, y3, x4, y4);
	stroke(100);
	text('Click', x1/2, y2);
}

mouseClicked = function() {
  if (mouseButton === LEFT) {
    if(clicked){
      clear();
        draw();
    }else{
      for (let i = 0; i <= steps; i++) {
        let t = i / steps;
    	  stroke(c, 250-c, 0);
          fill(c, 250-c, 0);
          let x = bezierPoint(x1, x2, x3, x4, t);
          let y = bezierPoint(y1, y2, y3, y4, t);
    // to colorize one part of the curve only 
    // you need to check the variable t, e.g.
    // between 0.2 and 0.8
          if(t>0.2 && t<0.8)
            ellipse(x, y, 1, 1)
            c=c+cStep;
      }
    }
    clicked = !clicked;
    c=cStep;
  }
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>

0
投票

您希望在两个t值之间提取Bézier曲线的子部分。重复这样做,您可以将Bézier曲线细分为N条曲线,每条曲线可以分别绘制和着色。

这个Javascript library看起来很合适(文档可以找到here)来满足这个需求。

相关的方法是.split(t1,t2).getLUT(steps),它返回t1和t2之间原始Bézier的子部分的点坐标的查找表。

现在使用Processing,迭代坐标表并在点之间调用Processing的line()方法绘制相关的曲线部分(原始Bézier曲线的某些细分)。

如果不这样做,请使用Processing的bezierPoint()方法自己生成点列表(注意必须分别调用X和Y坐标),将t递增一个足够小的值以充分采样较大的Bézier曲线。再次,使用line()迭代这些点以渲染子部分。

您在math.stackexchange here上也解决了您的问题(更具描述性)。


0
投票

以下是使用Pomax's Bezier Primer第7节中的de Casteljau算法的示例。您可以通过根据t的值更改笔划中的颜色值来更改曲线的颜色。在t <.25时,我将曲线绘制为红色

var setup = function(){
  createCanvas(250, 250);
  noLoop();
}

var draw = function(){
  var points = [];
  points[points.length] = new pt(90, 110);
  points[points.length] = new pt(25, 40);
  points[points.length] = new pt(230, 40);
  points[points.length] = new pt(150, 240);
  var t = 1;
  while (t >= 0){
    drawCurve(points, t);
    t-=.001;
    if (t < .25){
     stroke(250,0,0);     
    }
  }
}

function drawCurve(points, t){
  if(points.length==1){
    drawPoint(points[0])
  }
  else {
   var newpoints= [];
    for(i=0; i< points.length-1; i++){
      x = (1-t) * points[i].x + t * points[i+1].x
      y = (1-t) * points[i].y + t * points[i+1].y
      newpoints[i] = new pt(x,y);
    }
    drawCurve(newpoints, t)
   }
}

function pt(x, y){
  this.x = x;
  this.y = y;
}

function drawPoint(p){
  point(p.x, p.y);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>
© www.soinside.com 2019 - 2024. All rights reserved.