我正在寻找一种沿着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();
}
答案 0 :(得分:0)
这个问题有点不清楚。到
沿a的两个距离生成相同数量的点 指向另一个
您可以简单地在两点之间进行线性插值(简称为lerp)。 此功能内置于PVector's lerp()函数中。
该功能有三个参数:
您可以将标准化值视为百分比:
这是两个点之间的基本示例演示插值,其间有一定数量的点:
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--;
}
您可以将其作为演示程序运行:
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;
可以将功能封装到可重用的功能中:
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);
}
}
请注意,插值是线性的。对于您可能想要查看的曲线 高阶插值函数,如二次或三次。
Hermite curves是三次曲线的一个例子。
这是一个基本的公式:
这是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;
}
目前还不清楚你的目标是如何在你的观点之间进行插值,但希望上述概念可以帮助你实现目标。