0

首先,我画了很多圆圈,它们在轻微移动,因为我在圆圈的中心添加了噪点。这些圆圈是“不可见的”,因为它们与背景颜色相同。

其次,我画了一些结合ellipse(mouseX,mouseY,random(1,3),random(1,3)), rect,line等的图案。由于颜色的原因,图案也是“看不见的”。

第三,这就是问题所在,如果圆圈与图案的距离小于一定量,我想让圆圈出现(改变颜色)。

我如何计算这些圆圈的中心和图案边界之间的距离?它们都是因变量

然后我找到了一种思考方式:将数组中的每个元素与数组中的每个其他元素进行比较成为一个问题 https://forum.processing.org/topic/constantly-resizing-ellipse-based-on- distance,但我仍然不知道如何将形状函数修改ellipse(x,y,radius1,radius2)为数组。

可能是因为 Processing 中的形状函数封装得很好,不容易破解和使用。我找到了一种计算点到线距离的方法:processing.org/discourse/beta/num_1276644884.html

但是我不明白。请给我任何提示。谢谢。

4

3 回答 3

1

你的问题主要是关于几何和数学而不是关于编程,但它是这样的:

  • 两个圆的边界之间的最小距离:显然是它们的中心的距离,减去它们的半径之和。

  • 圆的边界和线段之间的最小距离:查看thisthisthis以及任何其他带有术语 的 Google 搜索结果minimum distance between point and line segment。再一次,您将不得不减去半径。

  • 圆的边界和矩形/多边形等之间的最小距离:每个单独段的所有距离的最小值。

  • 圆的边界和直线之间的最小距离:见这个

  • 圆和椭圆的边界之间的最小距离:搜索“点和椭圆之间的最小距离”。有很多结果,有些比其他的更直接。不要忘记减去圆的半径。

如果所有其他方法都失败了(例如对于任意形状),您可能必须逐点计算距离 - 不是很有效,但通常很有效。

一个重要的问题:您对几何重叠(即由公式定义)还是像素重叠感兴趣?根据绘图算法,两个形状的屏幕表示可能会重叠,而在数学上形状本身不会重叠,反之亦然。

于 2012-08-26T09:08:05.467 回答
1

有一个名为PVector的处理类可以为您完成很多这项工作。您可以使用继承并创建一个扩展Pvector 的新类。

或者您可以获取您的坐标并将它们动态更改为 PVector 以进行计算。

println(new PVector(x1, y1).dist(new PVector(x2, y2)));

注意:PVector 也适用于 3d 矢量和坐标。

于 2012-09-01T18:50:36.533 回答
0

在这一点上,您可能应该更多地担心学习编程的基础知识,而不是解决问题背后的数学。事实上,现在让我们把数学问题变得超级简单,这样代码就不会变得太复杂:假设你的图案是正方形,而你只对圆心到 ' 中心的距离感兴趣图案'/正方形。

例如, ellipse() 函数只会做一件事 - 将在屏幕上绘制一个椭圆,但您需要一些东西来跟踪您使用的椭圆的属性(如位置和大小)。

跟踪属性的一种方法是将它们存储在数组中:

int numEllipses = 100;
float[] ellipseXValues    = new float[numEllipses];
float[] ellipseYValues    = new float[numEllipses];
float[] ellipseSizeValues = new float[numEllipses];
//etc.

对于每个属性,您将使用一个数组,因为您将拥有多个椭圆“对象”。模式类似。如果您还不熟悉数组,那么以这种方式做事是一个很好的练习。你会注意到你的代码会很快变得很长,但是当你学习时,代码看起来并不重要:它更多的是理解和跟踪你所做的事情(而不是“咬得比咀嚼的多”)。

另一种方法是使用类。类很酷,因为它们允许您封装与您想到的想法相关的属性和功能。例如,您可以创建自己的Ellipse类或一个Pattern类,该类将包含您要使用的属性(如位置、颜色等),但也可以具有函数(如绘制()函数,椭圆将在屏幕上呈现自身)方式,但另一个模式)等等。这是一个例子:

class Circle{
  float x,y,vx,vy,size;//store position(x,y), velocity(vx,vy) and size
  color clr;           //store color
  Circle(float ax,float ay,float as,color ac){
    x = ax;
    y = ay;
    size = as;
    clr = ac;
    vx = random(-.1,.1);//random velocity
    vy = random(-.1,.1);
  }
  void update(int w,int h){
    x += vx;//update position based on velocity
    y += vy;
    if(x < 0 || x > w) vx *= -1;//check bounds and flip velocity if there's a collision
    if(y < 0 || y > h) vy *= -1;
  }
  void draw(){
    pushStyle();//start isolating drawing commands 
    noStroke();
    fill(clr);
    ellipse(x,y,size,size);
    popStyle();//stop isolating drawing commands 
  }

}

一个类就像一个模板/蓝图——它可以是你想要的任何东西。例如,您可以有一个Vehicle类,该类具有一个属性,该属性numberOfWheels确定从该类创建的实例/对象的外观:2 人的自行车,4 人的汽车等。类似地,您可以有一个Pattern类,它可能具有各种属性/与之相关的变量:条纹/点的数量,颜色列表等。

下面是一个如何使用 Circle 类的基本示例:

Circle c;
void setup(){
  size(400,400);
  smooth();
  c = new Circle(200,200,20,color(192));//create a new object from the template/class using the *new* keyword
}
void draw(){
  background(255);

  c.x = mouseX;//access and modify properties of the object
  c.y = mouseY;
  c.size = map(mouseX,0,width,20,200);
  c.clr  = color(map(mouseY,0,height,0,240));

  c.draw();//call a function/method of the object
}

注意定义/类和对象(用new实例化)之间的区别。如果您不熟悉类,请查看Daniel Shiffman的优秀对象教程。在处理中,您可以探索示例 > 基础 > 对象 > 对象

(不太重要:我正在使用map()函数轻松地将鼠标位置链接到圆的属性,如大小和颜色。)

现在您可以创建自己的类型/类,还可以创建此类对象的数组。Processing 附带一个基本示例:示例 > 基础 > 数组 > ArrayObjects

以下是我们如何在两个单独的数组中一起使用 Circle 类(和一个非常相似的 Square)类并检查距离:

int maxCircles = 20;
int maxSquares = 3;
float minDist  = 50;
Circle[] circles = new Circle[maxCircles];//create an array Circle objects/instances
Square[] squares = new Square[maxSquares];

void setup(){
  size(400,400);
  smooth();
  colorMode(HSB,360,100,100);
  for(int i = 0; i < maxCircles; i++) circles[i] = new Circle(random(width),random(height),random(4,10),color(0,0,100));
  for(int i = 0; i < maxSquares; i++) squares[i] = new Square(random(width),random(height),random(4,10),color(240));
}
void draw(){
  background(0,0,95);
  for(int i = 0; i < maxCircles; i++){
    circles[i].update(width,height);

    for(int j = 0; j < maxSquares; j++){
      squares[j].update(width,height);
      //use the dist() function to compute distances
      float distance = dist(circles[i].x,circles[i].y,squares[j].x,squares[j].y);
      if(distance < minDist){//based on that, if within a threshold, map colours/etc.
        circles[i].clr = color(  0,map(distance,0,minDist,100,0),100);
      }

      squares[j].draw();
    }
    circles[i].draw();
  }
}
class Circle{
  float x,y,vx,vy,size;//store position(x,y), velocity(vx,vy) and size
  color clr;           //store color
  Circle(float ax,float ay,float as,color ac){
    x = ax;
    y = ay;
    size = as;
    clr = ac;
    vx = random(-.1,.1);//random velocity
    vy = random(-.1,.1);
  }
  void update(int w,int h){
    x += vx;//update position based on velocity
    y += vy;
    if(x < 0 || x > w) vx *= -1;//check bounds and flip velocity if there's a collision
    if(y < 0 || y > h) vy *= -1;
  }
  void draw(){
    pushStyle();//start isolating drawing commands 
    noStroke();
    fill(clr);
    ellipse(x,y,size,size);
    popStyle();//stop isolating drawing commands 
  }

}
class Square{
  float x,y,vx,vy,size;
  color clr;
  Square(float ax,float ay,float as,color ac){
    x = ax;
    y = ay;
    size = as;
    clr = ac;
    vx = random(-.02,.02);//random velocity
    vy = random(-.02,.02);
  }
  void update(int w,int h){
    x += vx;
    y += vy;
    if(x < 0 || x > w) vx *= -1;
    if(y < 0 || y > h) vy *= -1;
  }
  void draw(){
    pushStyle();
    noStroke();
    fill(clr);
    rect(x-size/2,y-size/2,size,size);
    popStyle();
  }

}

正如您在注释代码中看到的那样,在对复杂概念进行了某种简化/封装之后,只需循环遍历数组并检查距离(使用dist())。

这是一个快速预览,小方块“假装”成图案并影响其周围圆圈的颜色:

圆形和正方形

您也可以在线或以下运行代码:

var maxCircles = 20;
var maxSquares = 3;
var minDist  = 150;
var circles = new Array(maxCircles);
var squares = new Array(maxSquares);

function setup(){
  createCanvas(400,400);
  smooth();
  colorMode(HSB,360,100,100);
  for(var i = 0; i < maxCircles; i++) circles[i] = new Circle(random(width),random(height),random(4,10),color(0,0,100));
  for(i = 0; i < maxSquares; i++)     squares[i] = new Square(random(width),random(height),random(4,10),color(240));
}
function draw(){
  background(0,0,95);
  for(var i = 0; i < maxCircles; i++){
    circles[i].update(width,height);
    for(var j = 0; j < maxSquares; j++){
      squares[j].update(width,height);
      var distance = dist(circles[i].x,circles[i].y,squares[j].x,squares[j].y);
      if(distance < minDist){
        circles[i].clr = color(  0,map(distance,0,minDist,100,0),100);
      }squares[j].draw();
    }
    circles[i].draw();
  }
}
function Circle(ax,ay,as,ac){
  this.x = ax;
  this.y = ay;
  this.size = as;
  this.clr = ac;
  this.vx = random(-.1,.1);//random velocity
  this.vy = random(-.1,.1);
  
  this.update = function(w,h){
    this.x += this.vx;
    this.y += this.vy;
    if(this.x < 0 || this.x > this.w) this.vx *= -1;
    if(this.y < 0 || this.y > this.h) this.vy *= -1;
  }
  this.draw = function(){
    push();
    noStroke();
    fill(this.clr);
    ellipse(this.x,this.y,this.size,this.size);
    pop();
  }
  
}
function Square(ax,ay,as,ac){
  this.x = ax;
  this.y = ay;
  this.size = as;
  this.clr = ac;
  this.vx = random(-.02,.02);//random velocity
  this.vy = random(-.02,.02);
  
  this.update = function(w,h){
    this.x += this.vx;
    this.y += this.vy;
    if(this.x < 0 || this.x > this.w) this.vx *= -1;
    if(this.y < 0 || this.y > this.h) this.vy *= -1;
  }
  this.draw = function(){
    push();
    noStroke();
    fill(this.clr);
    rect(this.x-this.size/2,this.y-this.size/2,this.size,this.size);
    pop();
  }
  
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>

希望这解释了处理该问题的一种基本方法。在您发现自己对语法和一些编程概念感到满意之后,应该更容易深入了解更多内容:

  • 您可能会发现数组有些限制,因为它们的大小是固定的,并且可以探索ArrayList
  • 您可能会发现基本距离函数对于您的复杂模式不够精确,并且可以找到其他计算距离的方法。

祝你好运

于 2012-08-27T08:44:29.323 回答