double Vektor::winkel(Vektor vektor) const { if (m_Zeilen != vektor.m_Zeilen || m_Spalten != vektor.m_Spalten) { return std::numeric_limits<float>::quiet_NaN(); } return acos(skalarprodukt(vektor) / (betrag() * vektor.betrag())) / M_PI * 180; }
/* Beschreibung: * prueft, ob ein Robutton mit einer Tischkante (eckiger Tisch) * kollidieren wuerde und behandelt die Kollision * Eingabewerte: * 1. Argument: Zeiger auf die Simulationsstruktur * 2. Argument: Index des zu untersuchenden Robuttons * Rueckgabewerte: * 0, wenn der Robutton nicht kollidiert ist * 1, wenn der Robutton kollidiert ist */ char pruefe_kollision_tischkante_eckig(struct simulation *s, int i) { int j; double d, m, delta_x, z, l; struct strecke st, kante; struct vektor u, a, f; struct vektor *schnittpunkt; /* alle Tischkanten durchlaufen */ for (j = 0; j < s->tisch->anzahl_ecken - 1; j++) { /* Strecke des Robuttons */ st.anfang = s->robuttons[i].position; st.ende = s->neue_positionen[i]; /* Strecke der Tischkante */ kante.anfang = s->tisch->ecken[j]; kante.ende = s->tisch->ecken[j + 1]; /* Bedingungen fuer eine Kollision */ if ((d = abstand_punkt_gerade(s->neue_positionen[i], s->tisch->ecken[j], s->tisch->ecken[j + 1])) <= 1.0 && (schnittpunkt = schnittpunkt_strecken(kante, st)) != NULL) { delta_x = s->tisch->ecken[j + 1].x - s->tisch->ecken[j].x; /* vertikale Gerade */ if (delta_x == 0) { /* x-Richtung wird umgekehrt */ s->robuttons[i].richtung.x *= (-1); /* neue Position berechnen */ if (s->robuttons[i].richtung.x > 0.0) s->neue_positionen[i].x = s->tisch->ecken[j].x + s->robuttons[i].richtung.x - d; else s->neue_positionen[i].x = s->tisch->ecken[j].x + s->robuttons[i].richtung.x + d; } else { /* Anstieg der Gerade bestimmen */ m = (s->tisch->ecken[j + 1].y - s->tisch->ecken[j].y) / delta_x; /* horizontale Gerade */ if (m == 0.0) { /* y-Richtung wird umgekehrt */ s->robuttons[i].richtung.y *= (-1.0); /* neue Position berechnen */ if (s->robuttons[i].richtung.y > 0.0) s->neue_positionen[i].y = s->tisch->ecken[j].y + s->robuttons[i].richtung.y - d; else s->neue_positionen[i].y = s->tisch->ecken[j].y + s->robuttons[i].richtung.y + d; } else { /* diagonale/schraege Gerade */ /* Punkt ausserhalb der Tischflaeche wird * an der Tischkante gespiegelt */ u.x = kante.ende.x - kante.anfang.x; u.y = kante.ende.y - kante.anfang.y; a.x = s->neue_positionen[i].x - kante.anfang.x; a.y = s->neue_positionen[i].y - kante.anfang.y; l = skalarprodukt(a, u) / skalarprodukt(u, u); f.x = kante.anfang.x + l * u.x; f.y = kante.anfang.y + l * u.y; /* neue Position berechnen */ s->neue_positionen[i].x = (-1.0) * s->neue_positionen[i].x + 2.0 * f.x; s->neue_positionen[i].y = (-1.0) * s->neue_positionen[i].y + 2.0 * f.y; /* neue Richtung berechnen */ s->robuttons[i].richtung.x = s->neue_positionen[i].x - schnittpunkt->x; s->robuttons[i].richtung.y = s->neue_positionen[i].y - schnittpunkt->y; /* Richtungsvektor zum Einheitsvektor machen */ z = betrag(s->robuttons[i].richtung); s->robuttons[i].richtung.x /= z; s->robuttons[i].richtung.y /= z; } } /* Speicher freigeben */ free(schnittpunkt); return (1); } } return (0); }
/* Beschreibung: * prueft, ob ein Robutton mit einer Tischkante (runder Tisch) * kollidieren wuerde und behandelt die Kollision * Eingabewerte: * 1. Argument: Zeiger auf die Simulationsstruktur * 2. Argument: Index des zu untersuchenden Robuttons * Rueckgabewerte: * 0, wenn der Robutton nicht kollidiert ist * 1, wenn der Robutton kollidiert ist */ char pruefe_kollision_tischkante_rund(struct simulation *s, int i) { double m, m2, n2, r, delta_x, l, z, d; struct vektor v, a, b, u, f; struct vektor *schnittpunkt; struct strecke st; /* Mittelpunkt */ v.x = s->tisch->ecken[0].x; v.y = s->tisch->ecken[0].y; /* Radius */ r = s->tisch->ecken[1].x; /* Strecke des Robuttons */ st.anfang = s->robuttons[i].position; st.ende = s->neue_positionen[i]; /* Bedingungen fuer die Kollision */ if (!ist_tischflaeche(s->tisch, s->neue_positionen[i].x, s->neue_positionen[i].y) && (schnittpunkt = schnittpunkt_strecke_kreis(st, v, r)) != NULL) { /* Tangente im Schnittpunkt ermitteln */ delta_x = schnittpunkt->x - v.x; /* horizontale Tangente */ if (delta_x == 0.0) { /* y-Richtung umkehren */ s->robuttons[i].richtung.y *= (-1.0); /* zwei Punkte der Tangente bestimmen */ a.x = schnittpunkt->x; a.y = schnittpunkt->y; b.x = schnittpunkt->x + 1.0; b.y = schnittpunkt->y; /* Abstand des Robuttons zur Tangente berechnen */ d = abstand_punkt_gerade(s->neue_positionen[i], a, b); /* neue Position berechnen */ if (s->robuttons[i].richtung.y > 0.0) s->neue_positionen[i].y = schnittpunkt->y + s->robuttons[i].richtung.y - d; else s->neue_positionen[i].y = schnittpunkt->y + s->robuttons[i].richtung.y + d; } else { /* Anstieg der Geraden vom Mittelpunkt * zum Schnittpunkt bestimmen */ m = (schnittpunkt->y - v.y) / delta_x; /* vertikale Tangente */ if (m == 0.0) { /* x-Richtung umkehren */ s->robuttons[i].richtung.x *= (-1); /* zwei Punkte der Tangente bestimmen */ a.x = schnittpunkt->x; a.y = schnittpunkt->y; b.x = schnittpunkt->x; b.y = schnittpunkt->y + 1.0; /* Abstand des Robuttons zur Tangente berechnen */ d = abstand_punkt_gerade(s->neue_positionen[i], a, b); /* neue Position berechnen */ if (s->robuttons[i].richtung.x > 0.0) s->neue_positionen[i].x = schnittpunkt->x + s->robuttons[i].richtung.x - d; else s->neue_positionen[i].x = schnittpunkt->x + s->robuttons[i].richtung.x + d; } else { /* Gleichung der Tangenten ermitteln */ m2 = (-1.0) / m; n2 = schnittpunkt->y - m2 * schnittpunkt->x; /* Punkt ausserhalb der Tischflaeche wird * an der Tangente gespiegelt */ u.x = 2.0 - 1.0; u.y = (m2 * 2.0 + n2) - (m2 * 1.0 + n2); a.x = s->neue_positionen[i].x - 1.0; a.y = s->neue_positionen[i].y - (m2 * 1.0 + n2); l = skalarprodukt(a, u) / skalarprodukt(u, u); f.x = 1.0 + l * u.x; f.y = (m2 * 1.0 + n2) + l * u.y; /* neue Position berechnen */ s->neue_positionen[i].x = (-1.0) * s->neue_positionen[i].x + 2.0 * f.x; s->neue_positionen[i].y = (-1.0) * s->neue_positionen[i].y + 2.0 * f.y; /* neue Richtung berechnen */ s->robuttons[i].richtung.x = s->neue_positionen[i].x - schnittpunkt->x; s->robuttons[i].richtung.y = s->neue_positionen[i].y - schnittpunkt->y; /* Richtungsvektor des Robuttons zum Einheitsvektor machen */ z = betrag(s->robuttons[i].richtung); s->robuttons[i].richtung.x /= z; s->robuttons[i].richtung.y /= z; } } free(schnittpunkt); return (1); } return (0); }
float Vektor::winkel(Vektor* v) { return acos((skalarprodukt(v))/((betrag()) * (v->betrag()))); }
float Vektor::betrag() const { return sqrt(skalarprodukt(*this)); }