0

Firstly, I draw lots of circles and they are moving slightly because I add noise in the center of a circle. These circles are "invisible" because they have the same color as the background.

Second, I draw some patterns combining ellipse(mouseX,mouseY,random(1,3),random(1,3)), rect, line, etc. The pattern is also "invisible" because of the color.

Third, and this is the problem, I want to make the circles show up (change color) if they have a distance from the patterns less than a certain amount.

How could I calculate the distance between those circles' center and the pattern's border? They are both dependent variables.

And then I found one way to think : to make it a problem of compare each element in the array with every other element in the array https://forum.processing.org/topic/constantly-resizing-ellipse-based-on-distance, but I still don't know how to modify shape function like ellipse(x,y,radius1,radius2)into an array.

Maybe because the shape functions in Processing are so well-packaged that they're not easy to break and use. I found a way to calculate Point to line distance : processing.org/discourse/beta/num_1276644884.html

However I don't understand it.Please give me any hint.Thanks.

Lain
  • 2,166
  • 4
  • 23
  • 47
kikkpunk
  • 1,287
  • 5
  • 22
  • 34
  • How is the distance defined? Distance between the centers of circles/ellipses or distance between the borders? – Ridcully Aug 26 '12 at 08:37
  • between the circles' center and the pattern's border. – kikkpunk Aug 26 '12 at 08:48
  • can you post a picture of the pattern? I thought it's only ellipses but reading your question again you also mention rectangles and lines. – Ridcully Aug 26 '12 at 08:49
  • Have you tried `Math.hypot()`? Please edit your question to include an [sscce](http://sscce.org/) that shows your esential approach. – trashgod Aug 26 '12 at 08:50

3 Answers3

1

Your question is mostly about geometry and mathematics than about programming, but here it goes:

  • Minimum distance between the borders of two circles: Obviously the distance of their centers, minus the sum of their radii.

  • Minimum distance between the border of a circle and a line segment: See this, this, this and any other result of a Google search with the terms minimum distance between point and line segment. Once again, you will have to subtract the radius.

  • Minimum distance between the border of a circle and a rectangle/polygon etc: Minimum of all distances for each separate segment.

  • Minimum distance between the border of a circle and a line: See this.

  • Minimum distance between the borders of a circle and an ellipse: Search for "minimum distance between point and ellipse". There are lots of results, some more straightforward than others. Don't forget to subtract the circle radius.

If all else fails (e.g. for arbitrary shapes) you may have to go point-by-point and compute the distance - not very efficient, but usually effective.

An important question: are you interested in geometric overlap (i.e. as defined by a formula) or in pixel overlap? Depending on the drawing algorithm, the on-screen representations of two shapes may overlap, while mathematically the shapes themselves do not and vice versa.

Community
  • 1
  • 1
thkala
  • 84,049
  • 23
  • 157
  • 201
  • See also methods available to classes implementing the [`Shape`](http://docs.oracle.com/javase/7/docs/api/java/awt/Shape.html) interface. – trashgod Aug 26 '12 at 09:15
  • @thkala, thx but i don't understand the examples you provided. i only know processing syntax whick draws shapes like: line(x1,y1,x2,y2),ellipse(x,y,radius1,radius2). all examples are here http://processing.org/learning/basics/ and i need to calculate distance between points on thess shapes. Maybe because the shape functions are so well-packaged that it's not easy to break and use it. i found a way to calculate Point to line distance http://processing.org/discourse/beta/num_1276644884.html – kikkpunk Aug 26 '12 at 13:05
1

There is processing class that does a lot of this work for you called PVector. You can use inheritance and create a new class that extends PVector.

Or you can take your coordinates and change them into a PVector on the fly for your calculations.

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

Note: PVector will also work for 3d vectors and coordinates.

Spudley
  • 166,037
  • 39
  • 233
  • 307
JAMESSTONEco
  • 2,051
  • 15
  • 21
0

At this point you should probably worry more about picking up the basics of programming than the maths behind solving your problem. In fact, let's make the math problem super simple for now, so the code doesn't get too complicated: let's pretend your patterns are squares and you're interested in only the distance from the centre of a circle to the centre of a 'pattern'/square.

The ellipse() function for example will only do one thing - will draw an ellipse on screen, but you will need something to keep track of the properties of the ellipse you use (like position and size).

One way to keep track of the properties is to store them in an array:

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

For each property you'll use an array since you'll have multiple ellipse 'objects'. Similar for patterns. If you're not already familiar with arrays, then doing things this way is a good exercise. You will notice you're code will get pretty long pretty fast, but what code looks like matters less when you learn: it's more about understand and keeping tracking of what you do (not "bitting more than what one can chew").

Another way to do this is to use classes. Classes are cool because they allow you to encapsulate properties and functionalities related to an idea you think of. For example you can create your own Ellipse class or a Pattern class which will hold the properties you want to use (like position, colour, etc.) but can also have functions (like a draw() function where an Ellipse would render itself on screen one way, but a Pattern in another) and so on. Here's an example:

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 
  }

}

A class is like a template/blueprint - it can be anything you want. For example you can have a Vehicle class which has a property numberOfWheels which determines how the instances/objects created from this class will look like: a bike for 2, car for 4, etc. Similarly you can have a Pattern class and it might have a various properties/variables related to it: number of stripes/dots, a list of colours, etc.

Here's a basic example of how to use the Circle class:

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
}

Notice the difference between the definition/class and the object (instantiated with new). In case you're not familiar with classes already check out Daniel Shiffman's excellent Objects tutorial. In Processing you can explore Examples > Basics > Objects > Objects.

(less important: I'm using the map() function to easily link mouse positions to properties of the circle like size and colour.)

Now that you can create your own type/class, you can also create arrays of such objects. There's a basic example that ships with Processing: Examples > Basics > Arrays > ArrayObjects

Here's how we use the Circle class (and a very similar Square) class together in two separate arrays and check distances:

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();
  }

}

As you can see in the commented code, after the complex concepts are somewhat simplified/encapsulated, it's just a matter of looping through arrays and checking distances (using dist()).

Here's a quick preview, where tiny squares 'pretend' to be pattens and affect the colour of circles around themselves:

Circles and Squares

You can also run the code online or bellow:

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>

Hopefully this explains one basic way to deal with the problem. After you've found yourself comfortable with the syntax and some programming concepts it should be a lot easier to dive into slightly more things:

  • you might find arrays somewhat limiting because of they're fixed size and could explore ArrayList
  • you might find the basic distance function is not precise enough for your complex patterns and can find other ways of computing distances.

Goodluck

George Profenza
  • 50,687
  • 19
  • 144
  • 218
  • Thx George, but can you explain this code more: circles[i].clr = color( 0,map(distance,0,minDist,100,0),100); i thought upper bound of the value's current range must be larger than the lower bound? BTW the color fading of the far distance seems not so well and i want to adapt it but get stuck in the above code. – kikkpunk Sep 01 '12 at 04:09
  • @i'mnotaprogrammer That's not so complicated, but maybe it's easier to understand if it's split on two lines:`float saturation = map(distance,0,minDist,100,0); circles[i].clr = color( 0,saturation,100);`. You're right, as described by the documentation, map takes 5 params, something like: `value, fromMin,fromMax,toMin,toMax`. I've used the last two values backwards because in my demo I wanted to have full saturation (100) on the minimum distance and no saturation(0) when the distance is larger, basically using 'fuller' colours as distance decreases. Feel free to use map colours as you see fit. – George Profenza Sep 01 '12 at 17:53