Schnittpunkt zu Kreis, Winkelberechnung
-
Hallo,
ich arbeite auf einem Image mit zwei weiteren Images. Zwischen diesen beiden zeichne ich eine Linie mit einem Pfeil an beiden Seiten. Dafür habe ich einen virtuellen Kreis um das einzelne Image herum und berechne den Schnittpunkt der Geraden mit diesem Kreis. An dieser Stelle soll die Pfeilspitze sein. Klappt bedingt, da die Verbindungslinie nicht wirklich in der Mittellinie ist. Die Pfeilspitze des Bis-Image wandert gut mit, aber beim Von geht es immer von einer Stelle ab, nicht der Mitte. Zudem will ich eine Funktion, und nicht Abhängigkeiten prüfen in welchem Quadranten sich Von / Bis befindet. Kann mir jemand helfen ?
if (img[iRelationVonZu[i][0]]->Top > img[iRelationVonZu[i][1]]->Top && img[iRelationVonZu[i][0]]->Left > img[iRelationVonZu[i][1]]->Left) { // BIS = oben links ia = img[iRelationVonZu[i][0]]->Top - img[iRelationVonZu[i][1]]->Top; //dynamic_cast<TImage*>(Sender)->Top; ib = img[iRelationVonZu[i][0]]->Left - img[iRelationVonZu[i][1]]->Left; //dynamic_cast<TImage*>(Sender)->Left; ic = sqrt(ia * ia + ib * ib); if (ic > 0) { iWinkel = (sin(ia / ic)); } iKx = (img[iRelationVonZu[i][1]]->Left + img[iRelationVonZu[i][1]]->Width / 2) + iRadius * cos(iWinkel); iKy = (img[iRelationVonZu[i][1]]->Top + img[iRelationVonZu[i][1]]->Height / 2) + iRadius * sin(iWinkel); ib2 = img[iRelationVonZu[i][0]]->Top + img[iRelationVonZu[i][0]]->Height / 2 - img[iRelationVonZu[i][1]]->Top + img[iRelationVonZu[i][1]]->Height / 2; //dynamic_cast<TImage*>(Sender)->Top; ia2 = img[iRelationVonZu[i][0]]->Left + img[iRelationVonZu[i][0]]->Width / 2 - img[iRelationVonZu[i][1]]->Left + img[iRelationVonZu[i][1]]->Width / 2; //dynamic_cast<TImage*>(Sender)->Left; ic2 = sqrt(ia2 * ia2 + ib2 * ib2); if (ic2 > 0) { iWinkel2 = 225 - (sin(ia2 / ic2)); } iKx2 = (img[iRelationVonZu[i][0]]->Left + img[iRelationVonZu[i][0]]->Width / 2) + iRadius * cos(iWinkel2); iKy2 = (img[iRelationVonZu[i][0]]->Top + img[iRelationVonZu[i][0]]->Height / 2) + iRadius * sin(iWinkel2); frmMain->Image1->Canvas->MoveTo(img[iRelationVonZu[i][0]]->Left + img[iRelationVonZu[i][0]]->Width / 2, img[iRelationVonZu[i][0]]->Top + img[iRelationVonZu[i][0]]->Height / 2); frmMain->Image1->Canvas->LineTo(img[iRelationVonZu[i][1]]->Left + img[iRelationVonZu[i][1]]->Width / 2, img[iRelationVonZu[i][1]]->Top + img[iRelationVonZu[i][1]]->Height / 2); cpic_draw_arrow(iKx, iKy, iKx2, iKy2, false); cpic_draw_arrow(iKx2, iKy2, iKx, iKy, false); }
-
Ein paar Kommentare wären ganz schön.
-
// Zur Laufzeit werden Images erzeugt img[] mit einer fortlaufender Nummer // iRelationVonZu ist ein zweidimensionaler Array, der die Nummern der erzeugten Images beinhaltet // iRelationVonZu[Von_Nummer][Nach_Nummer] // Bezogen auf das Von-Image habe ich es in 4 Quadranten eingeteilt. // Wenn sich das Von-Objekt rechts unterhalb des Zielobjektes (Bis) befindet if (img[iRelationVonZu[i][0]]->Top > img[iRelationVonZu[i][1]]->Top && img[iRelationVonZu[i][0]]->Left > img[iRelationVonZu[i][1]]->Left) { // BIS = oben links // Über Phytagoras Seiten a, b und c berechnen ia = img[iRelationVonZu[i][0]]->Top - img[iRelationVonZu[i][1]]->Top; ib = img[iRelationVonZu[i][0]]->Left - img[iRelationVonZu[i][1]]->Left; ic = sqrt(ia * ia + ib * ib); if (ic > 0) { // Winkel ausrechnen, den die Linie des Von-Images in Richtung Bis-Image einschlägt iWinkel = (sin(ia / ic)); } // Berechnen des Kreisschnittpunktes im Bis-Image // Hierbei gehe ich von einem imaginären Kreis aus, der um das Bis-Image gezogen ist, Mittelpunkt ist der Mittelpunkt des Bis-Images iKx = (img[iRelationVonZu[i][1]]->Left + img[iRelationVonZu[i][1]]->Width / 2) + iRadius * cos(iWinkel); iKy = (img[iRelationVonZu[i][1]]->Top + img[iRelationVonZu[i][1]]->Height / 2) + iRadius * sin(iWinkel); // Das gleiche dann für das andere Image ib2 = img[iRelationVonZu[i][0]]->Top + img[iRelationVonZu[i][0]]->Height / 2 - img[iRelationVonZu[i][1]]->Top + img[iRelationVonZu[i][1]]->Height / 2; //dynamic_cast<TImage*>(Sender)->Top; ia2 = img[iRelationVonZu[i][0]]->Left + img[iRelationVonZu[i][0]]->Width / 2 - img[iRelationVonZu[i][1]]->Left + img[iRelationVonZu[i][1]]->Width / 2; //dynamic_cast<TImage*>(Sender)->Left; ic2 = sqrt(ia2 * ia2 + ib2 * ib2); if (ic2 > 0) { iWinkel2 = 225 - (sin(ia2 / ic2)); } iKx2 = (img[iRelationVonZu[i][0]]->Left + img[iRelationVonZu[i][0]]->Width / 2) + iRadius * cos(iWinkel2); iKy2 = (img[iRelationVonZu[i][0]]->Top + img[iRelationVonZu[i][0]]->Height / 2) + iRadius * sin(iWinkel2); frmMain->Image1->Canvas->MoveTo(img[iRelationVonZu[i][0]]->Left + img[iRelationVonZu[i][0]]->Width / 2, img[iRelationVonZu[i][0]]->Top + img[iRelationVonZu[i][0]]->Height / 2); frmMain->Image1->Canvas->LineTo(img[iRelationVonZu[i][1]]->Left + img[iRelationVonZu[i][1]]->Width / 2, img[iRelationVonZu[i][1]]->Top + img[iRelationVonZu[i][1]]->Height / 2); // Pfeil-Funktion, die StartX, StartY, EndX, EndY Koordinaten erhält und am Ende die Spitze zeichnet. cpic_draw_arrow(iKx, iKy, iKx2, iKy2, false); cpic_draw_arrow(iKx2, iKy2, iKx, iKy, false); }
-
Einige Kleinigkeiten beachten und schon geht's!
- Phytagoras nicht nötig, Berechnung des Winkels über tan() möglich
- Grundsätzlich mit double rechnen, um Rundungsfehler zu vermeiden
- mit sprechenden Variablennamen idx, idy statt ia, ib vermeidet man Denkfehler
- Vor Umwandlung in int (für Koodinaten nötig!) 0.5 addieren um Rundungsfehler zu minimieren
- iWinkel und iWinkel2 sind identisch, Bewertung des Quadranten durch Vorzeichen bei r*sin() , bzw r*cos() möglichHier eine mögliche Veränderung des Codes:
#define IREL iRelationVonZu[i] if (img[IREL[0]]->Top > img[IREL[1]]->Top && img[IREL[0]]->Left > img[IREL[1]]->Left) { // BIS = oben links double ddx, ddy; double dWinkel; int iKx, iKy; int iKx2, iKy2; // Winkel der Images zueinander berechnen ddy = img[IREL[0]]->Top - img[IREL[1]]->Top; ddx = img[IREL[0]]->Left - img[IREL[1]]->Left; if (ddx!=0) { // Winkel ausrechnen, den die Linie des Von-Images in Richtung Bis-Image einschlägt dWinkel = tan(ddy/ddx); } // Berechnen des Kreisschnittpunktes im Bis-Image // Hierbei gehe ich von einem imaginären Kreis aus, der um das Bis-Image gezogen ist, Mittelpunkt ist der Mittelpunkt des Bis-Images // Koordinaten an img[0] iKx = ((img[IREL[1]]->Left + (double)img[IREL[1]]->Width / 2.0) + dRadius * cos(dWinkel) + 0.5); iKy = ((img[IREL[1]]->Top + (double)img[IREL[1]]->Height / 2.0) + dRadius * sin(dWinkel) +0.5); // Koordinaten an img[1] iKx2 = (((double)img[IREL[0]]->Left + (double)img[IREL[0]]->Width / 2.0) - dRadius * cos(dWinkel)+ 0.5); iKy2 = (((double)img[IREL[0]]->Top + (double)img[IREL[0]]->Height / 2.0) - dRadius * sin(dWinkel)+ 0.5); // Hilfslinie zur Kontrolle frmMain->Image1->Canvas->MoveTo(img[IREL[0]]->Left + img[IREL[0]]->Width / 2, img[IREL[0]]->Top + img[IREL[0]]->Height / 2); frmMain->Image1->Canvas->LineTo(img[IREL[1]]->Left + img[IREL[1]]->Width / 2, img[IREL[1]]->Top + img[IREL[1]]->Height / 2); // Pfeil-Funktion, die StartX, StartY, EndX, EndY Koordinaten erhält und am Ende die Spitze zeichnet. cpic_draw_arrow(iKx, iKy, iKx2, iKy2, false); cpic_draw_arrow(iKx2, iKy2, iKx, iKy, false); } }
-
Hallo,
vielen Dank !
Bei einem Winkel bis ca. 60° läuft alles wie es soll. Danach verschiebt es sich. Aber nun hab ich endlich mal den richtigen Ansatzpunkt ! Vielen Dank !
-
Hallo nochmal. Die Variante, zu der ich angefragt hatte läuft dank Bcbap.
Nun will ich noch folgendes erreichen:
Keine Verbindung in der Mitte sondern zwei Verbindungen zwischen den Images. Praktisch vom Mittelpunkt aus gesehen einige Pixel darüber und darunter. Dann wieder jeweils den Schnittpunkt der beiden Linien mit dem virtuellen Kreis berechnen. Das Ganze für beide Images.Hat da jemand einen Lösungsansatz oder gleiches schon mal umgesetzt ?