#I need some help creating a class/methods to calculate and display vectors.

1 messages · Page 1 of 1 (latest)

snow dagger
#

I think I'm heading in the right direction, but I'm thrashing a bit with how to write the constructor and methods.

I would like a few hints to get back on the right path.

I'm using Processing 4.5.2 Java core, and JDK 17, in IDEA CE.

I've created a class Vectorizer, which I want to take two sets of coordinates and convert them into a vector, so that I can display a line that extends past the 2nd xy point, as well as designate a point on the line that remains a constant distance away from the 1st xy point.

I've screwed up somewhere, as even though (I think) I'm passing new points to the .display method, the displayed line doesn't move.

Code to follow.

tight fjordBOT
#

<@&987246964494204979> please have a look, thanks.

snow dagger
#
class Vectorizer {
        // properties

        float startXPoint, startYPoint, thruXPoint, thruYPoint, dist, vx, vy, mag, x, y, wayPast, xExtendedPoint, yExtendedPoint;

        // constructor
        Vectorizer(float[] startPoint, float[] thruPoint, float distance) {

            startXPoint = startPoint[0];
            startYPoint = startPoint[1];
            thruXPoint = thruPoint[0];
            thruYPoint = thruPoint[1];
            wayPast = distance *2;
            vx = thruXPoint - startXPoint;
            vy = thruYPoint - startYPoint;
            mag = sqrt((vx * vx) + (vy * vy));


            vx /= mag;
            vy /= mag;
            x = (startXPoint + vx * (mag - distance));
            y = (startYPoint + vy * (mag - distance));
            xExtendedPoint = (startXPoint + vx * (mag - wayPast));
            yExtendedPoint = (startYPoint + vy * (mag - wayPast));
            // methods

        }

        void display(float[] startPoint, float[] thruPoint, float distance) {
        line(startXPoint, startYPoint, xExtendedPoint, yExtendedPoint);
        circle(x,y,3);
        }
        void update(float[] startPoint, float[] thruPoint, float distance) {

        }
    }
sonic gazelle
#

well,
where do you return it to origin?

#

you need to translate it to origin, scale the magnitude, then translate it back to position

snow dagger
#

I don't understand 'return it to origin', and I thought x, y, xExtendedPoint, yExtendedPoint were translated back to position.

sonic gazelle
snow dagger
#

For edification, I don't know much about vector math, except that it's somewhat required to calculate a fixed point away from the start of a line.

snow dagger
#

Again, I just want to find a point, say, 100 points away from the start of the line.

sonic gazelle
#

yes, so you just translate the vector to the plan origin 0,0
scale the vector to the magnitude needed,
then translate it back to position.

snow dagger
#

I thought I was doing that.

#
    public float[] distanceFromEnd(float dist, float x0, float y0, float x1, float y1) {


        //              colorStroke(hsb);
        //
        float vx = x1 - x0;
        float vy = y1 - y0;
        float mag = sqrt((vx * vx) + (vy * vy));

        // println(mag);

        vx /= mag;
        vy /= mag;
        float x = (x0 + vx * (mag - dist));
        float y = (y0 + vy * (mag - dist));
        //     linePointList.add(new float[]{x,y});

        return new float[]{x, y};

This was the method that I used in old code that worked. Now, I'm trying to rewrite it into more OOP style code.

sonic gazelle
#

oop style would be to make a method for each part and reuse it.

#

how to calculate magnitude

#

how to translate the vector

snow dagger
#

Why, yes. That's what I'm having trouble with.

sonic gazelle
#

how to scale it

snow dagger
sonic gazelle
#
class Vectorizer {
  Vector origin;
  Vector target;
  // constructor
  Vectorizer(Vector origin, Vector target, double distance) {
  }

  record Vector(double x, double y) {
  }
}

I would start with this.

#

Then just go from there

#
class Vectorizer {
  Vector origin;
  Vector target;

  // constructor
  Vectorizer(Vector origin, Vector target, double distance) {
    var v = difference(target, origin);
    v = scale(v, distance / magnitude(v));
    v = addition(origin, v);
    this.origin = origin;
    this.target = v;
  }

  Vector scale(Vector vector, double scale) {
    return new Vector(vector.x * scale, vector.y * scale);
  }

  Vector difference(Vector v1, Vector v2) {
    return new Vector(v1.x - v2.x, v1.y - v2.y);
  }

  Vector addition(Vector v1, Vector v2) {
    return new Vector(v1.x + v2.x, v1.y + v2.y);
  }

  double magnitude(Vector v) {
    return Math.sqrt(v.x * v.x + v.y * v.y);
  }


  record Vector(double x, double y) {
  }
}
#

btw

#

I fucked up

snow dagger
#

eh, join the club. :)

sonic gazelle
#
class Vectorizer {
  Vector origin;
  Vector target;

  // constructor
  Vectorizer(Vector origin, Vector target, double distance) {
    var v = target.difference(origin);
    v = v.scale(distance / v.magnitude());
    v = v.addition(origin);
    this.origin = origin;
    this.target = v;
  }


  record Vector(double x, double y) {
    Vector scale(double scale) {
      return new Vector(x * scale, y * scale);
    }

    Vector difference(Vector v2) {
      return new Vector(x - v2.x, y - v2.y);
    }

    Vector addition(Vector v2) {
      return new Vector(x + v2.x, y + v2.y);
    }

    double magnitude() {
      return Math.sqrt(x * x + y * y);
    }
  }
}
#

Somewhere it is a choice

#

what make more sense

#

oop does not exist really

snow dagger
#

I gather 'origin' is the start of the vector? That'd be the point on the larger wheel.

sonic gazelle
#

yes

snow dagger
#

'target' would be the point I would like the vector to pass through? That would be the point on the smaller wheel.

sonic gazelle
#

yes

snow dagger
#

magnitude would be the distance from the origin?

sonic gazelle
#

not really, magnitude is just the length of the vector

snow dagger
#

magnitude would be the length of the vector from the origin?

sonic gazelle
#

the question does not make sense

snow dagger
#

magnitude would be a length of a vector from the origin towards the target?

sonic gazelle
#

In mathematics, a norm is a function from a real or complex vector space to the non-negative real numbers that behaves in certain ways like the distance from the origin: it commutes with scaling, obeys a form of the triangle inequality, and zero is only at the origin. In particular, the Euclidean distance in a Euclidean space is defined by a nor...

#

if you want the length between the 2 vector

#

you make the difference of the 2 vector

snow dagger
#

I only have one vector.

sonic gazelle
#

and calculate the magnitude

#

no, you got origin + target

snow dagger
#

can I not make a vector out of those two points, with the addition of a magnitude?

sonic gazelle
#

yes, but you would lose the origin

#

That information would be lost

#

so it is useless to do it, as you would then need other variable to keep it in memory

snow dagger
#

I don't understand how it would be lost, because I would have the X,Y coordinate.

sonic gazelle
#

a line must be formed of 2 points

#

these 2 points are the 2 vector

snow dagger
#

FYI, I don't require vectors, if there's another way to calculate a fixed point on a line that extends from an origin past a target.

sonic gazelle
#

a vector is an imaginary line from the plan origin to the point.

#

in 2d case, 0,0

#

vector and point are the same

#

just different way to name it

#

you still need the 2 points

#

so even if you named it point, you would apply the same logic on it

#

it is named vector only because a math guy studied points a lot

#

so he observed rule to manipulate them, and noted them down, gave them name

snow dagger
#

Ok, I'm gonna stop you right here.

I needed help with syntax and formatting a known working formula, re-writing it into a class/method style.

I do not wish to go further down into vector math or get tangled up in semantics.

#

I thought it was vector math. I thought magnitude meant length from a starting point. I might have thought wrong.

willow swift
snow dagger
#

I do not know what that means, or how to go about it.

willow swift
#
class Point {
  float x, y;
  // constructor, et 
}
snow dagger
#

Just that?

willow swift
snow dagger
#

Can you give me a hint on how to do this?

willow swift
#

this: float x0, float y0
becomes: Point p0

this: float startXPoint, float startYPoint
becomes: Point startPoint

etc

snow dagger
#

Yes, I can see how that'd be easier to read.

#

I don't quite know how to implement it.

willow swift
#

also replace new float[]{x, y} by a Point too

willow swift
snow dagger
#

(did I accidentally put I was higher than novice programmer somewhere?)

willow swift
willow swift
#

well

#

you seemed to understand classes so

snow dagger
#

And that my gateway to Java was Processing ?

#

I made 1 class that worked the 1st time, and that seems to have been beginner's luck. :)

#

and I made that class just this afternoon.

willow swift
#
class Point {
  float x, y;
  Point(float x, float y) {
    this.x = x;
    this.y = y;
  }
}

do you understand how to use this ?

#

if it can help:

tight fjordBOT
#

A classic example of a simple Java class Person that has two fields String name and int age, with corresponding getter and setter methods:

public class Person {
  private String name;
  private int age;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return name;
  }

  public int getAge() {
    return age;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setAge(int age) {
    this.age = age;
  }
}

Simple usage example:

Person person = new Person("John", 20);
System.out.println(person.getName()); // John
System.out.println(person.getAge()); // 20
person.setAge(21);
System.out.println(person.getAge()); // 21
snow dagger
#

yes, it means the thing that 'this' is.

willow swift
#

I mean

snow dagger
#

recursively.

willow swift
#

do you understand how you can use this Point class ?

#

as for applying a vector, you can simply do:

float x = cos(angle) * magnitude;
float y = sin(angle) * magnitude;

@snow dagger

snow dagger
#
public class SpirographOOP extends PApplet {
    
    Point startingPoint;
    Point targetPoint;
snow dagger
#

Oh, angle.

#

right. I have two points, not the angle.

willow swift
snow dagger
#

In Logo, or turtle graphics, I would just set my position to the starting point, set heading towards [target point], then fwd magnitude

snow dagger
#

Logo? it's an ancient language that was used to draw lines and do recursive stuff.

#

like, 1960s.

willow swift
#
Point forward(Point start, Vector vector) {
  float x = start.x + cos(vector.angle) * vector.magnitude;
  float y = start.y + sin(vector.angle) * vector.magnitude;
  return new Point(x, y);
}
#

something like that

snow dagger
willow swift
snow dagger
#

also, while we're on the Points class, lets work on getting me up to speed on that.

willow swift
snow dagger
#

how would I get it to accept a float[]?

willow swift
snow dagger
#

[0] has X, [1] has Y.

willow swift
#

new float[]{x, y} becomes new Point(x, y)

snow dagger
#
  static public float[] hypotrochoid(float degreeAngle,
                                           float ringSize,
                                           float rotorSize,
                                           float rotorPivotDistance) {
            float[] hypotrochoid = new float[4];

            float pivotXPosition,
                    pivotYPosition,
                    rotorXPosition,
                    rotorYPosition;


            pivotXPosition = ((ringSize - rotorSize) * cos(radians(degreeAngle))) + (rotorPivotDistance * cos(radians(((ringSize - rotorSize) / rotorSize) * degreeAngle)));
            pivotYPosition = ((ringSize - rotorSize) * sin(radians(degreeAngle))) - (rotorPivotDistance * sin(radians(((ringSize - rotorSize) / rotorSize) * degreeAngle)));

            rotorXPosition = ((ringSize - rotorSize) * cos(radians(degreeAngle)));
            rotorYPosition = ((ringSize - rotorSize) * sin(radians(degreeAngle)));

            hypotrochoid[0] = rotorXPosition;
            hypotrochoid[1] = rotorYPosition;
            hypotrochoid[2] = pivotXPosition;
            hypotrochoid[3] = pivotYPosition;


            return hypotrochoid;
        }
willow swift
#

replace float[4] by Point[2]

#

instead of 4 indexes with x1, y1, x2, y2
you have p1, p2

snow dagger
#
 static public Point[] hypotrochoid(float degreeAngle,
                                           float ringSize,
                                           float rotorSize,
                                           float rotorPivotDistance) {
            ///float[] hypotrochoid = new float[4];
            Point[] hypotrochoid = new Point[2];
            float pivotXPosition,
                    pivotYPosition,
                    rotorXPosition,
                    rotorYPosition;

Like this?

willow swift
#

yes

snow dagger
#

ok, let me fix what broke when I did that... (or is there a shortcut I can use in IntelliJ?

willow swift
#

not for this kind of stuff

snow dagger
#

'k. it'll take me a few moments.

#

ping you when I'm done?

willow swift
#

just so you know

snow dagger
#

The Processing methods don't like Point too much.

willow swift
snow dagger
#

ty

willow swift
#

but yea please mention me if you have a question

snow dagger
#
             hypotrochoid[0].x = rotorXPosition;
             hypotrochoid[0].y = rotorYPosition;
             hypotrochoid[1].x = pivotXPosition;
             hypotrochoid[1].y = pivotYPosition;


            return hypotrochoid;

Is this how I return a Point?

#

@willow swift

#
Point[] returnXY() {
            Point[] gears = hypotrochoid(ringRotorAngle, ringSize, rotorSize, rotorPivotPoint);
            return new Point[]{gears};

That's giving me trouble.

willow swift
snow dagger
#
  startingPoint =  Point(test1.returnPoint);

Last error.

snow dagger
#

test1 is a hypotrochoid.

willow swift
#

Point without new ?

#

what is returnPoint ?

#

startingPoint = test1.returnPoint ?

#

@snow dagger

snow dagger
#
   Point[] returnPoint() {
            Point[] gears;
            gears = hypotrochoid(ringRotorAngle, ringSize, rotorSize, rotorPivotPoint);
            //   return new Point[]{gears[1]};
            return gears;
        }
#
  test1 = new HypotrocoidGear(75, 0, false);
#

Ok, it's getting late for me too. I commented out the error, and now I'm getting a runtime error

java.lang.NullPointerException: Cannot assign field "x" because "hypotrochoid[0]" is null
at SpirographOOP$HypotrocoidGear.hypotrochoid(SpirographOOP.java:190)

#

I'll review the code tomorrow, and see why it's null.

willow swift
#

create the array last line

#

and do new point

snow dagger
#
 static public Point[] hypotrochoid(float degreeAngle,
                                           float ringSize,
                                           float rotorSize,
                                           float rotorPivotDistance) {
            ///float[] hypotrochoid = new float[4];
            Point[] hypotrochoid = new Point[2];
            float pivotXPosition,
                    pivotYPosition,
                    rotorXPosition,
                    rotorYPosition;


            pivotXPosition = ((ringSize - rotorSize) * cos(radians(degreeAngle))) + (rotorPivotDistance * cos(radians(((ringSize - rotorSize) / rotorSize) * degreeAngle)));
            pivotYPosition = ((ringSize - rotorSize) * sin(radians(degreeAngle))) - (rotorPivotDistance * sin(radians(((ringSize - rotorSize) / rotorSize) * degreeAngle)));

            rotorXPosition = ((ringSize - rotorSize) * cos(radians(degreeAngle)));
            rotorYPosition = ((ringSize - rotorSize) * sin(radians(degreeAngle)));

            hypotrochoid[0].x = rotorXPosition;
            hypotrochoid[0].y = rotorYPosition;
            hypotrochoid[1].x = pivotXPosition;
            hypotrochoid[1].y = pivotYPosition;


            return hypotrochoid;
        }
#

do what now?

#

hypotrochoid[0] = {rotorXPosition, rotorYPosition};

#

Shall we revisit this tomorrow?

#

Yeah, I'm outta here for the night. Thanks for all your help, both of you.

#

I'll rewrite that method entirely for the Point class.

willow swift
# snow dagger ```java static public Point[] hypotrochoid(float degreeAngle, ...
 static public Point[] hypotrochoid(float degreeAngle,
                                           float ringSize,
                                           float rotorSize,
                                           float rotorPivotDistance) {

            float pivotXPosition = ((ringSize - rotorSize) * cos(radians(degreeAngle))) + (rotorPivotDistance * cos(radians(((ringSize - rotorSize) / rotorSize) * degreeAngle)));
            float pivotYPosition = ((ringSize - rotorSize) * sin(radians(degreeAngle))) - (rotorPivotDistance * sin(radians(((ringSize - rotorSize) / rotorSize) * degreeAngle)));

            float rotorXPosition = ((ringSize - rotorSize) * cos(radians(degreeAngle)));
            float rotorYPosition = ((ringSize - rotorSize) * sin(radians(degreeAngle)));

            return new Point[]{ new Point(rotorXPosition, rotorYPosition), new Point(pivotXPosition, pivotYPosition) };
        }
snow dagger
#

Thank you; I see what you did there, and now it's running again.

I'll convert the rest of my code to use Point throughout the day.

snow dagger
#

As I looked up how to best write helper methods for Processing's circle() and line() methods, Gemini mentioned the Processing class PVector, which has vector math built in.

I try not to vibe-code, but occasionally Gemini spits out something useful.

snow dagger
#

OK, I'm almost there. Using my old method, with X and Ys, I'm able to get a point at a constant distance from one end of the line. (the black dot, in this animation)...

#

I would like to convert that old method to use PVector, but I'm not sure what that method is actually doing.

#

Well, I have the method returning a PVector, but it's still taking two sets of Xs and Ys.

#

The method:

    public PVector distanceFromEnd(float dist, float x0, float y0, float x1, float y1) {

        float vx = x1 - x0;
        float vy = y1 - y0;
        float mag = sqrt((vx * vx) + (vy * vy));

        vx /= mag;
        vy /= mag;
        float x = (x0 + vx * (mag - dist));
        float y = (y0 + vy * (mag - dist));

        return new PVector(x,y);
    }
#

and here's the abomination that calls the method:

 vCircle(distanceFromEnd(25, gear2.getPivot().x, gear2.getPivot().y,gear1.getPivot().x, gear1.getPivot().y ), 2);
#

so it looks like it's subtracting the 2nd PVector from the 1st, and something else?

#

These are the methods available with the PVector class. I looked through most of them, and read the PVector supplementary documentation...

oblique moat
snow dagger
#

Atan2...

#

Is my method reasonable, then? I can clean it up for the PVector stuff.

#

There, down to a nice:
vCircle(distanceFromEnd(gear2.getPivot(), gear1.getPivot(), 30), 3);

#

Thank you for all your help!

tight fjordBOT
#

Closed the thread.

snow dagger
#

Here's some initial output from the code I was working on. I'll add some colour later, and animate some changing params.

Thanks again for the help!