A function is required to limit the line (known by its coordinates) along the length

I need a function that takes a string (known by its coordinates) and return a string with the same angle, but limited to a specific length .

My code gives the correct values only when the line is turned "right"
(proven empirically, sorry).

Did I miss something?

public static double getAngleOfLine(int x1, int y1, int x2, int y2) {
  double opposite = y2 - y1;
  double adjacent = x2 - x1;

  if (adjacent == Double.NaN) {
    return 0;
  }

  return Math.atan(opposite / adjacent);
}

// returns newly calculated destX and destY values as int array
public static int[] getLengthLimitedLine(int startX, int startY,
    int destX, int destY, int lengthLimit) {

  double angle = getAngleOfLine(startX, startY, destX, destY);

  return new int[]{
        (int) (Math.cos(angle) * lengthLimit) + startX,
        (int) (Math.sin(angle) * lengthLimit) + startY
      };
}

      

BTW: I know returning arrays in Java are silly, but this is just for example.

0


a source to share


6 answers


In Python, because I don't have a Java compiler:



import math

def getLengthLimitedLine(x1, y1, x2, y2, lengthLimit):
    length = math.sqrt((x2-x1)**2 + (y2-y1)**2)
    if length > lengthLimit:
       shrink_factor = lengthLimit / length
       x2 = x1 + (x2-x1) * shrink_factor
       y2 = y1 + (y2-y1) * shrink_factor
    return x2, y2

print getLengthLimitedLine(10, 20, 25, -5, 12)
# Prints (16.17, 9.71) which looks right to me 8-)

      

+2


a source


It would be easier to just think of it as a vector. Normalize it by dividing my value, then multiply by the factor of the desired length.



For your example, however, try Math.atan2.

+3


a source


This is a simple problem if you understand anything about vectors.

Given two points (x1, y1) and (x2, y2), you can compute a vector from point 1 to 2:

v12 = (x2-x1) i + (y2-y2) j

where i and j are unit vectors in the x and y directions.

You can calculate the value of v by taking the square root of the sum of the squares of the components:

v = sqrt ((x2-x2) ^ 2 + (y2-y1) ^ 2)

The unit vector from point 1 to point 2 is v12 divided by its value.

With this in mind, you can calculate a point along the unit vector to multiply the unit vector by the length at the desired distance and add that to point 1.

+1


a source


Encapsulate the line in a class, add a unit method and a scale method.

public class Line {
private float x;
private float y;

public Line(float x1, float x2, float y1, float y2) {
    this(x2 - x1, y2 - y1);
}

public Line(float x, float y) {
    this.x = x;
    this.y = y;
}

public float getLength() {
    return (float) Math.sqrt((x * x) + (y * y));
}

public Line unit() {
    return scale(1 / getLength());
}

public Line scale(float scale) {
    return new Line(x * scale, y * scale);

}
}

      

Now you can get a string of arbitrary length l by calling

Line result = new Line(x1, x2, y1, y2).unit().scale(l);

      

+1


a source


It is not necessary to use a trigger which may have some nasty edges. Just use similar triangles:

public static int[] getLengthLimitedLine(int startX, int startY,
    int destX, int destY, int lengthLimit)
{
    int deltaX = destX - startX;
    int deltaY = destY - startY;
    int lengthSquared = deltaX * deltaX + deltaY * deltaY;
    // already short enough
    if(lengthSquared <= lengthLimit * lengthLimit)
        return new int[]{destX, destY};

    double length = Math.sqrt(lengthSquared);
    double newDeltaX = deltaX * lengthLimit / length;
    double newDeltaY = deltaY * lengthLimit / length;

    return new int[]{(int)(startX + newDeltaX), (int)(startY + newDeltaY)};
}

      

+1


a source


Just use the Pythagorean theorem , for example:

public static int[] getLengthLimitedLine(int start[], int dest[], int lengthLimit) {
    int xlen = dest[0] - start[0]
    int ylen = dest[1] - start[1]
    double length = Math.sqrt(xlen * xlen + ylen * ylen)

    if (length > lengthLimit) {
        return new int[] {start[0], start[1],
                start[0] + xlen / lengthLimit,
                start[1] + ylen / lengthLimit}
    } else {
        return new int[] {start[0], start[1], dest[0], dest[1];}
    }
}

      

0


a source







All Articles