Objekt entlang eines Funktionsgraphens bewegen

Hallo,

momentan versuche ich ein kleines 2D-Spiel zu programmieren, wo man mit nem Raumschiff durchs Weltall fliegt. Jetzt versuche ich umzusetzen, dass sich das Raumschiff entlang einer Route bewegt, die durch eine ganzrationale Funktion definiert ist.

Mein Ansatz bis jetzt:

Das Raumschiff hat eine gewisse Geschwindigkeit. Jetzt möchte ich wissen, wo genau das Raumschiff nach einer bestimmten Zeit ist. Dazu habe ich die Länge des Funktionsgraphen (s = v*t) gegeben. Daraus muss ich jetzt den x-Wert der Funktion bestimmen. Ich habe herausbekommen, dass die Länge des Graphens folgendermaßen definiert ist:
Integral[Länge des Graphen] = Integral[(sqrt(1+f'(x)^2) dx]

Die Funktion beschreibe ich mit einem Array der Faktoren, ein Beispiel:
f(x) = 2x^2 + 0.5 --> factors[0] = 0.5 ; factors[1] = 0 ; factors[2] = 2
Die Faktoren sind also für die jeweiligen Exponenten gespeichert: factors * x ^ i
Ich habe bereits die Methoden zum Ableiten, Stammfunktion (mit c = 0) bilden, den y-Wert berechnen und Funktionsterm quadrieren geschrieben und diese scheinen zu funktionieren. Jetzt habe ich das Problem, dass ich keine Ahnung habe, wie ich die Wurzel aus einem Funktionsterm ziehe. Dazu bräuchte ich soweit ich weiß sowas wie ne quadratische Ergänzung für Polynome. Ich dachte, dass mir hier vielleicht jemand von euch helfen könnte.

Falls ihr euch die Klasse mal anschauen wollt:
Java:
public class PolynominalFunction extends Function{
	
	double[] factors;
	
	public PolynominalFunction(double[] factors) {
		this.factors = factors;
	}
	
	@Override
	public double getY(double x) {
		double result = 0;
		for (int i = 0 ; i < factors.length ; i++){
			if (factors[i] == 0)
				continue;
			if (i == 0)
				result += factors[i];
			else
				result += factors[i]*Math.pow(x, i);
		}
		return result;
	}

	@Override
	public PolynominalFunction derive() {
		if (factors.length == 0)
			return new PolynominalFunction(new double[]{});
		double[] newFactors = new double[factors.length-1];
		for (int i = 1 ; i < factors.length ; i++)
			newFactors[i-1] = factors[i]*i;
		return new PolynominalFunction(newFactors);
	}

	@Override
	public PolynominalFunction antiderive() {
		if (factors.length == 0)
			return new PolynominalFunction(new double[]{});
		double[] newFactors = new double[factors.length+1];
		for (int i = 0 ; i < factors.length ; i++)
			newFactors[i+1] = factors[i]/(i+1);
		return new PolynominalFunction(newFactors);
	}
	
	public String serialize(){
		String s = null;
		for (int i = factors.length-1 ; i >= 0 ; i--){
			if (factors[i] == 0)
				continue;
			if (s == null)
				s = factors[i]+"*x^"+i;
			else{
				if (factors[i] > 0)
					s += "+";
				s += factors[i]+"*x^"+i;
			}
		}
		return s;
	}

	@Override
	public PolynominalFunction square() {
		if (factors.length == 0)
			return new PolynominalFunction(new double[]{});
		double[] newFactors = new double[factors.length*2];
		for (int i = 0 ; i < factors.length ; i++){
			newFactors[i*2] += factors[i]*factors[i];
			for (int k = i+1 ; k < factors.length ; k++){
				newFactors[i+k] += 2*factors[i]*factors[k];
			}
		}
		return new PolynominalFunction(newFactors);
	}

Ist mein Ansatz vielleicht Falsch? Gibt's da was einfacheres?
Ich bin für Vorschläge offen 😀

Falls es Probleme damit gibt meinen Ansatz zu verstehen sag bescheid, dann werde ich das versuchen zu illustrieren.
 
Zuletzt bearbeitet:
Wenn du Java 8 verwendest, kannst du das ganze mit Lambda Ausdrücken deutlich kürzer formulieren.
z.B. mittles java.util.function.DoubleUnaryOperator

Java:
static double integrateLength(DoubleUnaryOperator f, double x1, double x2, double dx) {
  double result = 0;
  double lastX = x1, lastY = f.applyAsDouble(lastX);
  for(double x = x1+dx; x <= x2; x += dx) {
    double y = f.applyAsDouble(x);
    result += Math.sqrt((x - lastX) * (x - lastX) + (y - lastY) * (y - lastY));
    lastX = x; lastY = y;
  }
  return result;
}

public static void main(String[] args) {
  DoubleUnaryOperator f = x -> 2*x*x + 3*x - 7;
  System.out.println(integrateLength(f, 0, 10, 0.1));
}
 
Zuletzt bearbeitet:
Du könntest übrigens auch deine selbst definierte Function Klasse zu einem Interface machen und dieses dann als @FunctionalInterface deklarieren. Dann packst du da "integrateLength " als default Methode rein und überschreibst das in der PolynominalFunction Klasse. Denn für Polynome ist deine Klasse schneller und genauer als die allgemeine Lösung, die ich gepostet habe. Dafür funktioniert meine Methode aber mit jeder beliebigen Funktion.
 
So, ich habe mir den Code jetzt mal nach einer längeren Pause angesehen (davor nur überflogen). Mein Problem damit ist (falls ich es richtig verstanden habe), dass es nur eine Nährung ist, welche für eine größere Genauigkeit mehr Rechenzeit braucht. Ich halte sowas einfach für suboptimal. Man kann ja auch die Fläche unter einer Funktion exakt per Integralrechnung bestimmen und muss nicht mit der Streifenmethode arbeiten.
Scheinbar ist ja die Methode die ich suche diese hier:

Integral[Länge des Graphen] = Integral[(sqrt(1+f'(x)^2) dx]

Dabei habe ich soweit jedes Problem gelöst, bis auf eins: die Wurzel aus einem Polynom zu ziehen. Kann mir da vielleicht jemand einen Tipp geben, welchen Ansatz ich verfolgen muss? Mein Kopf kommt nicht mehr mit, wenn ich die quadratische Ergänzung auf beliebig viele Polynomglieder ausweiten möchte. Das erscheint mir einfach extrem kompliziert, aber wahrscheinlich gibt es dafür einen relativ einfachen Algorithmus. Wenn das quadrieren so einfach ist (s. Methode oben) muss das Wurzelziehen auch machbar sein.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben