Вопрос

I am breaking my neck trying to solve this... The point should be located on border at place where mouse is pointing. In other words on crossing between rectangle borderline and a line between rectangle center and mouse pointer. I need to use trigonometry somehow as rectangle might be rotating. Below code (in processing) enables me to draw point but only on south border...

int size = 200;

void setup() {
  size(1200,500);
  smooth();
  ellipseMode(CENTER);
  rectMode(CENTER);

}

void draw() {
  background(255);
  noFill();

  PVector center = new PVector(width/2,height/2);
  PVector mouse = new PVector(mouseX, mouseY);

  float mouseDistance = PVector.dist(center,mouse);

  mouse.sub(center); // mouse coordinates relative to center point

  float t = atan2(mouse.y, mouse.x);

  float borderDistance = (size/2) / sin(t); 
  float bx = cos(t) * borderDistance;
  float by = sin(t) * borderDistance;

  pushMatrix();
    translate(center.x, center.y);
    strokeWeight(5);
    stroke(255,0,0);
    point(0,0);
    point(mouse.x, mouse.y);
    point(cos(t)*size/2, sin(t)*size/2);
    point(bx,by);
    strokeWeight(1);
    stroke(0);
    ellipse(0, 0, size, size);
    rect(0,0, size, size);
    stroke(0,255,0);
    line(0, 0, mouse.x, mouse.y);
  popMatrix();
}
Это было полезно?

Решение

Okay here's the math that will be involved to give you the location of your desired point.

Diagram for reference:

Problem Diagram

To find the Green point, all we need to do is find the find the height and the width of the imaginary rectangle (see image), which are labeled as Adj and Opp respectively, and add those values to the Center point.


If you remember SOH CAH TOA, we'll leverage TOA:

Tan(Theta) = Opposite / Adjacent 

which can be re-arranged to:

Opposite = Tan(Theta) * Adjacent

So we'll need to first find Adjacent (Adj) and Theta.


Consulting the diagram, Adj is obviously the difference in y between Orange and Center:

Adj = Orange.y - Center.y

But we don't know Orange? Well, Orange would be equal to Center plus half the height of the rectangle:

Orange = (Center.x, Center.y + Rect.Height/2)

Subbing the value of Orange back into our Adj calculation:

Adj = Center.y + Rect.Height/2 - Center.y
Adj = Rect.Height/2

Next we need to find Theta.

enter image description here

Rerfering back to SOH CAH TOA CAH:

Cos(Theta) = Adjacent / Hypotenuse
Theta = acos(Adjacent / Hypotenuse)  //Inverse cosine

We already know that Adj = Rect.Height/2 from earlier, so we just need to find Hyp. To find Hyp we can use the distance formula which says:

d = sqrt((x2 - x1)^2 + (y2 - y1)^2)

In our case:

Hyp = sqrt((Center.x - Mouse.x)^2 + (Center.y - Mouse.y)^2) 

So now we have everything we need for Theta:

Theta = acos(Adj / Hyp)  //Inverse cosine

Finally, we have what we need for Opp:

Opp = Tan(Theta) * Adjacent

Which means we have everything we need to answer your question:

Green = (Center.x + Opp, Center.y + Adj)

Notes:

  • This is the "on paper math" using degrees. A lot of programming languages deal with radians instead of degrees, so you may have to do some converting.

  • As @Jerry Andrews pointed out, there will be four different cases to this problem, which correspond to the four different sides of the rectangle that your drawing point could fall on:

To determine the quadrant, he first needs the angle between the center of the rectangle and any corner--thus, atan(height/width). This will give the half-angle (center-to-green, if green is on a corner). Then atan(mouse.y/mouse.x) will provide the angle of the line from the rectangle center to the mouse cursor (because in his code, the mouse is located relative to the center of the rectangle).

Другие советы

OK! i have managed to solve the point on border issue. processing sketch and code available under this link

I used atan2() function to calculate mouseTheta and then needed to play with quadrants:

 // north
      borderPoint = new PVector(tan(mouseTheta-HALF_PI)*r, -r);
 // east
      if(mouseTheta > TWO_PI-QUARTER_PI || mouseTheta < QUARTER_PI) 
         borderPoint = new PVector(r, tan(mouseTheta)*r);
 // south
      if(mouseTheta >= QUARTER_PI && mouseTheta < QUARTER_PI+HALF_PI) 
         borderPoint = new PVector(-tan(mouseTheta-HALF_PI)*r, r); 
 // west
      if(mouseTheta >= HALF_PI+QUARTER_PI && mouseTheta < PI+QUARTER_PI) 
         borderPoint = new PVector(-r,-tan(mouseTheta)*r); 

looks ugly but works... thanks!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top