沿着PShape轮廓走并划分它们?

时间:2016-10-07 17:41:49

标签: processing contour

我正在寻找一种沿着PShape轮廓找到点的正确方法。

我的目标是沿着从给定点到另一个点(右距离和左距离)的两个距离生成相同数量的点,然后在相同步骤编号的两个点之间的确切中心标记一个点在每一边。 (我不确定我是否容易理解,我不能附加img,所以我附上处理代码)。

我认为完成它的第一步是计算路径后起点和终点之间的确切距离。也许我错了。

非常欢迎任何有关此事的帮助。

PGraphics g ;
PVector[] values = new PVector[7];

void setup(){
  size(1024,768,P3D);
  fillVal();
  smooth();
}

void draw(){
  background(0);
  drawSiluette(g);
}

void fillVal(){
  values[0]=new PVector ( 336.0, 272.0, 0.0 );
  values[1]=new PVector ( 305.0, 428.0, 0.0 );
  values[2]=new PVector ( 489.0, 516.0, 0.0 );
  values[3]=new PVector ( 639.0, 400.0, 0.0);
  values[4]=new PVector ( 565.0, 283.0, 0.0 );
  values[5]=new PVector ( 469.0, 227.0, 0.0 );
  values[6]=new PVector ( 403.0, 216.0, 0.0 );
}


void drawSiluette(PGraphics _s){
  _s = createGraphics(width,height);
  pushMatrix();
  _s.beginDraw();
  _s.noFill();
  _s.strokeWeight(3);
  _s.stroke(255);
  _s.beginShape();  
  for(int i = 0; i <values.length;i++){
    if(i==0 || i==values.length-1){
      for(int it = 0; it<2;it++)
         _s.curveVertex(values[0].x,values[0].y);
    }else   
        _s.curveVertex(values[i].x,values[i].y);
  }
  _s.endShape(CLOSE);
  popMatrix();
  _s.endDraw();
  image(_s,0,0);


  //start and end points
  pushMatrix();
  noStroke();
  fill(255,0,0);
  ellipseMode(CENTER);
  ellipse(values[0].x,values[0].y,10,10);
  ellipse(values[int(values.length/2)].x,values[int(values.length/2)].y,10,10);
  popMatrix();
}

1 个答案:

答案 0 :(得分:0)

这个问题有点不清楚。到

  

沿a的两个距离生成相同数量的点   指向另一个

您可以简单地在两点之间进行线性插值(简称为lerp)。 此功能内置于PVector's lerp()函数中。

该功能有三个参数:

  1. 起点
  2. 结束点
  3. 标准化值,它是介于0.0和1.0之间的值
  4. 您可以将标准化值视为百分比:

    • 0.0 = 0%
    • 0.25 = 25%
    • 1.0 = 100%

    这是两个点之间的基本示例演示插值,其间有一定数量的点:

    PVector from = new PVector(100,100);
    PVector to   = new PVector(300,300);
    
    int numPoints = 10;
    
    void setup(){
      size(400,400);
      fill(0);
    }
    void draw(){
      background(255);
    
      for(int i = 0; i <= numPoints; i++){
        //compute interpolation amount = a number from 0.0 and 1.0 , where 0 = 0% along the line and 1.0 = 100 % along the line (0.5 = 50%, etc.)
        float interpolationAmount = (float)i / numPoints;
        //float interpolationAmount = map(i,0,numPoints,0.0,1.0);
    
        //linearly interpolate point based on the interpolation amount
        PVector interpolatedPoint = PVector.lerp(from,to,interpolationAmount);
        //render the point on screen
        ellipse(interpolatedPoint.x,interpolatedPoint.y,10,10);
      }
      text("numPoints: " + numPoints,10,15);
    }
    
    void mouseDragged(){
      if(keyPressed) {
        to.set(mouseX,mouseY);
      }else{
        from.set(mouseX,mouseY);
      }
    }
    
    void keyPressed(){
      if(keyCode == UP)   numPoints++;
      if(keyCode == DOWN && numPoints > 0) numPoints--;
    }
    

    您可以将其作为演示程序运行:

    &#13;
    &#13;
    var from,to;
    
    var numPoints = 10;
    
    function setup(){
      createCanvas(400,400);
      fill(0);
      
      from = createVector(100,100);
      to   = createVector(300,300);
    }
    function draw(){
      background(255);
      
      for(var i = 0; i <= numPoints; i++){
        //compute interpolation amount = a number from 0.0 and 1.0 , where 0 = 0% along the line and 1.0 = 100 % along the line (0.5 = 50%, etc.)
        //var interpolationAmount = (float)i / numPoints;
        var interpolationAmount = map(i,0,numPoints,0.0,1.0);
        
        //linearly interpolate point based on the interpolation amount
        var interpolatedPoint = p5.Vector.lerp(from,to,interpolationAmount);//PVector.lerp(from,to,interpolationAmount);
        //render the point on screen
        ellipse(interpolatedPoint.x,interpolatedPoint.y,10,10);
      }
      text("usage:\nclick & drag to move start point\nhold a key pressed while clicking and drag to move end point\nuse LEFT/RIGHT arrow to change number of points: " + numPoints,10,15);
    }
    
    function mouseDragged(){
      if(keyIsPressed) {
        to.set(mouseX,mouseY);
      }else{
        from.set(mouseX,mouseY);
      }
    }
    
    function keyPressed(){
      if(keyCode == LEFT_ARROW)   numPoints++;
      if(keyCode == RIGHT_ARROW && numPoints > 0) numPoints--;
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>
    &#13;
    &#13;
    &#13;

    可以将功能封装到可重用的功能中:

    void drawPointsInbetween(PVector from,PVector to,int numPoints){
      for(int i = 0; i <= numPoints; i++){
        //compute interpolation amount = a number from 0.0 and 1.0 , where 0 = 0% along the line and 1.0 = 100 % along the line (0.5 = 50%, etc.)
        float interpolationAmount = (float)i / numPoints;
        //float interpolationAmount = map(i,0,numPoints,0.0,1.0);
    
        //linearly interpolate point based on the interpolation amount
        PVector interpolatedPoint = PVector.lerp(from,to,interpolationAmount);
        //render the point on screen
        ellipse(interpolatedPoint.x,interpolatedPoint.y,10,10);
      }
    }
    

    回到你的代码,有一点是突出的,虽然它与你的主要问题无关,但事实是你每秒多次创建一个新的PGraphics实例。你可能不想这样做。目前,您应该能够直接进入Processing而不需要PGraphics。

    PVector[] values = new PVector[7];
    
    void setup(){
      size(1024,768,P3D);
      fillVal();
      smooth();
    }
    
    void draw(){
      background(0);
      drawSiluette(g);
    }
    
    void fillVal(){
      values[0]=new PVector ( 336.0, 272.0, 0.0 );
      values[1]=new PVector ( 305.0, 428.0, 0.0 );
      values[2]=new PVector ( 489.0, 516.0, 0.0 );
      values[3]=new PVector ( 639.0, 400.0, 0.0);
      values[4]=new PVector ( 565.0, 283.0, 0.0 );
      values[5]=new PVector ( 469.0, 227.0, 0.0 );
      values[6]=new PVector ( 403.0, 216.0, 0.0 );
    }
    
    
    void drawSiluette(PGraphics _s){
      //_s = createGraphics(width,height);
      pushMatrix();
      //_s.beginDraw();
      noFill();
      strokeWeight(3);
      stroke(255);
      beginShape();  
      for(int i = 0; i <values.length;i++){
        if(i==0 || i==values.length-1){
          for(int it = 0; it<2;it++)
             curveVertex(values[0].x,values[0].y);
        }else   
            curveVertex(values[i].x,values[i].y);
      }
      endShape(CLOSE);
      popMatrix();
    
    
      //start and end points
      pushMatrix();
      noStroke();
      fill(255,0,0);
      ellipseMode(CENTER);
      ellipse(values[0].x,values[0].y,10,10);
      ellipse(values[int(values.length/2)].x,values[int(values.length/2)].y,10,10);
      popMatrix();
    }
    

    在函数之间添加点就像这样简单:

    PVector[] values = new PVector[7];
    
    int numPoints = 10;
    
    void setup(){
      size(1024,768,P3D);
      fillVal();
      smooth();
    }
    
    void draw(){
      background(0);
      drawSiluette(g);
    }
    
    void fillVal(){
      values[0]=new PVector ( 336.0, 272.0, 0.0 );
      values[1]=new PVector ( 305.0, 428.0, 0.0 );
      values[2]=new PVector ( 489.0, 516.0, 0.0 );
      values[3]=new PVector ( 639.0, 400.0, 0.0);
      values[4]=new PVector ( 565.0, 283.0, 0.0 );
      values[5]=new PVector ( 469.0, 227.0, 0.0 );
      values[6]=new PVector ( 403.0, 216.0, 0.0 );
    }
    
    
    void drawSiluette(PGraphics _s){
      //_s = createGraphics(width,height);
      pushMatrix();
      //_s.beginDraw();
      noFill();
      strokeWeight(3);
      stroke(255);
      beginShape();  
      for(int i = 0; i <values.length;i++){
        if(i==0 || i==values.length-1){
          for(int it = 0; it<2;it++)
             curveVertex(values[0].x,values[0].y);
        }else   
            curveVertex(values[i].x,values[i].y);
      }
      endShape(CLOSE);
      popMatrix();
    
    
      //start and end points
      pushMatrix();
      noStroke();
      fill(255,0,0);
      ellipseMode(CENTER);
      ellipse(values[0].x,values[0].y,10,10);
      ellipse(values[int(values.length/2)].x,values[int(values.length/2)].y,10,10);
      popMatrix();
    
      //draw inbetween points
      for(int i = 1 ;  i < values.length; i++){
        drawPointsInbetween(values[i-1],values[i],numPoints);
      }
      //draw last to first
      drawPointsInbetween(values[values.length-1],values[0],numPoints);
    }
    void drawPointsInbetween(PVector from,PVector to,int numPoints){
      for(int i = 0; i <= numPoints; i++){
        //compute interpolation amount = a number from 0.0 and 1.0 , where 0 = 0% along the line and 1.0 = 100 % along the line (0.5 = 50%, etc.)
        float interpolationAmount = (float)i / numPoints;
        //float interpolationAmount = map(i,0,numPoints,0.0,1.0);
    
        //linearly interpolate point based on the interpolation amount
        PVector interpolatedPoint = PVector.lerp(from,to,interpolationAmount);
        //render the point on screen
        ellipse(interpolatedPoint.x,interpolatedPoint.y,10,10);
      }
    }
    

    这是一个预览: interpolation between points preview

    请注意,插值是线性的。对于您可能想要查看的曲线 高阶插值函数,如二次或三次。

    Hermite curves是三次曲线的一个例子。

    这是一个基本的公式:

    Hermite Curve Formula

    这是Hermite曲线上的基本处理演示插值点:

    float percent = 0;
    PVector P0 = new PVector(10,90);//1st control pt
    PVector T0 = new PVector(300,200);//1st anchor pt - NOTE! The anchors are relative to the controls
    PVector P1 = new PVector(400,90);//2nd control pt
    PVector T1 = new PVector(-100,400);//2nd anchor pt
    PVector[] points = {P0,T0,P1,T1};
    PVector pointAtPercent;
    
    void setup(){
      size(500,500);
      reset();
    }
    
    void reset(){
        P1.x = 200 + random(200);//randomize a wee bit
        T1.x = random(-100,100);
        percent = 0;
        background(255);
        loop();
    }
    void draw() {
        pointAtPercent = hermite(percent, points);//compute point
    
        //render on screen
        ellipse(pointAtPercent.x,pointAtPercent.y,10,10);
    
        //update percentage of traversal along curve
        percent += .015;
    
        //if the curve has been drawn, stop drawing
        if(percent >= 1) noLoop();
    }
    
    void mousePressed(){
      reset();
    }
    
    PVector hermite(float t,PVector[] points){
        PVector result = new PVector();
        result.x = (2 * pow(t,3) - 3 * t * t + 1) * points[0].x+
                    (pow(t,3) - 2 * t * t + t) * points[1].x + 
                    (- 2 * pow(t,3) + 3*t*t) * points[2].x +
                    ( pow(t,3) - t*t) * points[3].x;
        result.y = (2 * pow(t,3) - 3 * t * t + 1) * points[0].y+
                    (pow(t,3) - 2 * t * t + t) * points[1].y + 
                    (- 2 * pow(t,3) + 3*t*t) * points[2].y +
                    ( pow(t,3) - t*t) * points[3].y;
        return result;
    }
    

    目前还不清楚你的目标是如何在你的观点之间进行插值,但希望上述概念可以帮助你实现目标。