kostenloser Webspace werbefrei: lima-city


Ermitteln Punkt in Fläche?

lima-cityForumProgrammiersprachenJava

  1. Autor dieses Themas

    pixilab

    Kostenloser Webspace von pixilab

    pixilab hat kostenlosen Webspace.

    Lang ists her mit Mathe. Ich bin zu doof um folgende Aufgabe zu lösen, kann mir jemand helfen?

    Einfaches Beispiel.

    Hab ein Viereck auf einer Zeichenfläche:

    Kantenlänge = a
    Position auf dem Zeichenfeld = offsetX, offsetY
    Mauskoordinate = mausX, mausy

    Nun ist das Viereck von Kante zu Kante in 4 Teile aufgeteilt.

    Wie stelle ich fest, ob die Maus sich im oberen, unteren rechten oder linken Viertel des Vierecks befindet?

  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. maus_im_bild = mausposition - offset
    wenn maus_im_bild kleiner als horizontale/2 dann maus=links sonst maus=rechts
    wenn maus_im_bild kleiner als vertikale/2 dann maus=oben sonst maus=unten
  4. hm, wenn du gänzlich auf eine mathematische Lösung verzichten willst, dann würde ich dir folgendes Vorschlagen:

    - Du kennst alle notwendigen Punkte. Bau dir für jede deiner 4 Dreiecke ein GeneralPath-Objekt. Dann kannst du die Funktion contains eines GeneralPath-Objektes aufrufen, an der du die Maus-Position übergibst. Ist sie drin, so kriegst du ein true zurück, ansonsten false.

    Edit:

    Meinst du eigentlich so ein Viereck:
    -------
    |  |  |
    -------
    |  |  |
    -------

    oder so ein Viereck:
    ----
    |\/|
    |/\|
    ----


    Beitrag zuletzt geändert: 5.12.2010 18:16:16 von tangoal
  5. Autor dieses Themas

    pixilab

    Kostenloser Webspace von pixilab

    pixilab hat kostenlosen Webspace.

    @druid
    Ja, so wäre es einfach. ^^

    Der Schnitt ist wie ein X von der oberen linken Ecke zur unteren rechten Ecke und oberen rechten Ecke zur unteren linken Ecke.
    Ich knobel die ganze Zeit, wie man feststellt wenn sich die Maus zwischen drei sich schneidenden Geraden befindet.

    Wie würde es denn Mathematisch aussehen :)?


  6. ah, ok, also ASCII-Zeichnung Nummer 2... so sieht das bei dir aus:-)

    Dann passt mein Lösungsvorschlag ja haargenau:-)
  7. X, Y sei die Position der Maus innerhalb des Quadrats mit Ursprung in der linken oberen Ecke (sollte in Java doch so sein?), A sei die Seitenlänge. Die fallende Diagonale lässt sich als X = f(Y) = Y darstellen. Die steigende Diagonale ist dann natürlich X = f(Y) = A - Y.

    Folglich gilt:
    Link, genau dann, wenn A - Y > X > Y
    Rechts, genau dann, wenn A - Y < X < Y
    Oben, genau dann, wenn Y > X und A - Y > X
    Unten, genau dann, wenn Y < X und A - Y < X

    Ich hoffe ich hab keinen Denkfehler drin.

    Beitrag zuletzt geändert: 5.12.2010 19:09:24 von nikic
  8. pixilab schrieb:
    @druid
    Ja, so wäre es einfach. ^^

    Der Schnitt ist wie ein X von der oberen linken Ecke zur unteren rechten Ecke und oberen rechten Ecke zur unteren linken Ecke.
    Ich knobel die ganze Zeit, wie man feststellt wenn sich die Maus zwischen drei sich schneidenden Geraden befindet.

    Wie würde es denn Mathematisch aussehen :)?


    Die Zunahme der horizontalen (und hier ist es mal richtig gut, daß der Computer nur Treppchen kann und keine Kurven oder Schrägen) Linie von der senkrechten Seitefläche zur Diagonalen ist doch proportional und lässt sich dazu noch in Pixeln abzählen.
    Du kannst z.B. sagen auf eine Pixelzeile senkrecht, kommen 2 Pixel dazu, oder auf y Zeilen habe ich einen Zuwachs von n Pixeln in der Horizontalen.
    Sagen wir der Zuwachs ist zwei Pixel pro Zeile. Dann liegt die Maus im linken Feld, wenn sie in Zeile 10 auf der X-Koordinate weniger als 20 hat. Also x-Position_Maus < Zeile*Zuwachs. Allerdings gibt es hier im Grenzbereich der Diagonalen Ungenauigkeiten (eben, weil der Rechner nur Treppchen kann). Wenn der Zuwachs gerade ist, kannst Du die Diagonale selber in eine linke und eine rechte Hälfte teilen, sonst mußt Du würfeln. Letzteres in einer Formel sorgt natürlich für Ungenauigkeiten.
    In der Mitte der Vertikalen Linie ist natürlich das Maximum erreicht. Von Da an hast Du eine Abnahme, die dem Zuwachs entspricht

    also bis Mitte Länge(Pixelzeile)+Zuwachs, ab Mitte Länge(Pixelzeile)-Abnahme. Damit kannst Du für jede Zeile bestimmen, wie groß der Abstand der Maus zur linken Seite des Vierecks sein darf, um sich noch im linken Feld zu befinden.

    Für alle anderen Felder gilt Äquivalentes

    Beitrag zuletzt geändert: 5.12.2010 18:40:57 von druid
  9. Autor dieses Themas

    pixilab

    Kostenloser Webspace von pixilab

    pixilab hat kostenlosen Webspace.

    Danke euch, das hilft mir weiter :)
  10. Man kann sich mit der Idee mit der Steigung folgendes überlegen:

    Drei Punkte A, C, M machen sie eine Linkskurve oder eine Rechtskurve wenn man von A über C nach M geht?
    Erstmal verschieben wir sie, so dass A auf den Nullpunkt fällt.

    Also haben wir jetzt die Punkte Formel: (0,0),\; (C_x - A_x, C_y - A_y),\; (M_x - A_x, M_y - A_y)

    Die Steigung s der Geraden durch A und C ist Formel: s = \frac{C_y - A_y}{C_x - A_x}.

    Wenn gilt: Formel: s \cdot (M_x - A_x) < M_y - A_y dann liegt der Punkt M über der Gerade, also ist es eine Linkskurve.
    Wenn gilt: Formel: s \cdot (M_x - A_x) > M_y - A_y dann liegt der Punkt M unter der Gerade, also ist es eine Rechtskurve.
    Wenn gilt: Formel: s \cdot (M_x - A_x) = M_y - A_y dann liegt der Punkt M genau auf der Gerade.

    So können wir uns (indem wir diese drei Formeln auf beiden Seiten noch mit Formel: C_x - A_x multiplizieren) diese Funktion überlegen.

    Sie sagt uns ob die Punkte A - C - M eine Linkskurve (positiver Rückgabewert) oder eine Rechtskurve (negativer Rückgabewert) machen (Rückgabewert = Null, falls sie auf einer Geraden liegen):

    int isLeft(int ax, int ay, int cx, int cy, int mx, int my)
    {
        return (c.x - a.x)*(m.y - a.y) - (m.x - a.x)*(c.y - a.y);
    }

    Sie funktioniert sogar, wenn die Punkte C und A direkt übereinander liegen, also Formel: C_x = A_x, oder wenn C links von A liegt. Warum das auch funktioniert, kann man leider nur mit analytischer Geometrie erklären.

    Dann machen wir einfach:.

    int locatePoint(int offsetX, int offsetY, int a, int mausX, int mausX)
    { int ret, acm, bdm;
    	if ( (mausX < offsetX) || (offsetX > offsetX + a) || (mausY < offsetY) || (mausY > offsetY + a) ){
    		ret = -1; //Spezieller Wert wenn der Punkt nicht im Quadrat liegt.
    	}
    	else{
    	acm = isLeft(offsetX, offsetY, offsetX + a, offsetY + a, int mausX, int mausX); 
    	bdm = isLeft(offsetX + a, offsetY, offsetX, offsetY + a, int mausX, int mausX);
    	// was jetzt folgt bitte sauber mit if-else machen!
    	if (acm < 0 && bdm > 0) ret = 1;
    	if (acm < 0 && bdm < 0) ret = 2;
    	if (acm > 0 && bdm < 0) ret = 3;
    	if (acm > 0 && bdm > 0) ret = 4;
    	if (acm == 0 0 || bdm == 0) ret = 0; // spezieller Wert, wenn der Punkt genau auf einer der beiden Diagonalen liegt. Evtl. noch weiter Fallunterscheidungen einbauen
    	}
    }


    Diese Funktion gibt 1 zurück für das Dreieck unten, 3 für das Dreieck oben, 4 für das Dreieck links, 2 für das Dreieck rechts. Kann sein, das ein Fehler drin ist, aber das Prinzip stimmt definitiv.

    Beitrag zuletzt geändert: 5.12.2010 20:25:56 von utgard
  11. Autor dieses Themas

    pixilab

    Kostenloser Webspace von pixilab

    pixilab hat kostenlosen Webspace.

    Oha, hier wird einem geholfen :)

    Vielen dank nochmal. Hab die Mathematische Lösung gewählt, funktioniert supper.
    Hier meine Funktion. Man kann damit die Größe des gesamten Viereck-Feldes und seine Position festlegen.
    Verwendungszweck ist, eine Kollisionsbestimmung, wenn ein Gegenstand dagegen prallt, damit man weiß in welche Richtung der Abprall erfolgen soll.

    private Border[] fieldBorder(int[] position, int[] offset) {	
    		int a = Map.BLOCK_DIMENSION;		
    		int x = position[0];
    		int y = position[1];
    		
    		int offX = offset[0];
    		int offY = offset[1];
    
    		int nx = (x-offX);
    		int ny = (y-offY);
    		
    		Border borderX = null, borderY = null;
    		
    		if(x<=(a+offX) && x>offX && y<=(a+offY) && y>offY) {
    			if(nx>ny && nx<(a-ny)) {
    				borderY = Border.BOTTOM;
    				System.out.println("top");
    			}
    			if(nx<ny && nx>(a-ny)) {
    				borderY = Border.TOP;
    				System.out.println("bottom");
    			}
    			if(ny<nx && ny>(a-nx)) {
    				borderX = Border.LEFT;
    				System.out.println("right");
    			}
    			if(ny>nx && ny<(a-nx)) {
    				borderX = Border.RIGHT;
    				System.out.println("left");
    			}
    		}
    		return new Border[] {borderX, borderY};
    	}
  12. Sehr gut!

    Und wenn du das ganze mal statt mit einem Quadrat mit einem Rechteck brauchen solltest, dann kannst du meine Funktion isLeft() nehmen. Die ist nämlich so allgemein programmiert, dass sie in jeder erdenklichen Situation berechnen kann, wo der Punkt M von der Strecke AC aus gesehen liegt.

    Bei einer Linkskurve wie dieser gibt sie 1 zurück:
    M- - - - - -C
              .
           .
        .
     A



    Bei einer Rechtskurve wie dieser gibt sie -1 zurück:
    '
                 C .
              .        . 
           .             M
        .
     A
  13. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!