nicht rechteckiges element

  • Allgemein

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    nicht rechteckiges element

    Hey leute,

    wie ist es möglich ein element in einer beliebigen form zu machen? damit meine ich das man beliebig viele ecken machen kann, o.ä.

    damit ihr es euch besser vorstellen könnt... es ist für eine landkarte, wo man halt die einzelnen länder anklicken kann.
    Das zeichnen sollte mit GDI+ kein Problem sein - DrawPolygon.
    Bei der Kollisionsabfrage ist etwas mehr Code erforderlich. Schau dir am besten einfach mal an, wie ich es in MathUtils gemachte habe. Interessant sollte dabei die Polygon-Klasse sein.
    Also das wäre die nötige Funktion:
    Spoiler anzeigen

    C-Quellcode

    1. public static bool Contains(this IPolygon value, Point2D p)
    2. {
    3. var alpha = 0;
    4. var points = value.GetPoints();
    5. var v1 = points[points.Length - 1];
    6. //Startquadranten initialisieren
    7. var q1 = 0;
    8. if (v1.Y <= p.Y)
    9. if (v1.X <= p.X)
    10. q1 = 0;
    11. else
    12. q1 = 1;
    13. else if (v1.X <= p.X)
    14. q1 = 3;
    15. else
    16. q1 = 2;
    17. foreach (var v2 in points)
    18. {
    19. //Quadrant des Punktes bestimmen
    20. var q2 = 0;
    21. if (v2.Y <= p.Y)
    22. if (v2.X <= p.X)
    23. q2 = 0;
    24. else
    25. q2 = 1;
    26. else if (v2.X <= p.X)
    27. q2 = 3;
    28. else
    29. q2 = 2;
    30. //Quadrant auf Gesammtdrehung anwenden
    31. switch ((q2 - q1) & 3)
    32. {
    33. case 0:
    34. break;
    35. case 1:
    36. alpha += 1;
    37. break;
    38. case 3:
    39. alpha -= 1;
    40. break;
    41. default:
    42. var zx = ((v2.X - v1.X) * (p.Y - v1.Y) / (v2.Y - v1.Y)) + v1.X;
    43. if (p.X == zx)
    44. return true;
    45. if ((p.X > zx) == (v2.Y > v1.Y))
    46. alpha -= 2;
    47. else
    48. alpha += 2;
    49. break;
    50. }
    51. v1 = v2;
    52. q1 = q2;
    53. }
    54. return System.Math.Abs(alpha) == 4;
    55. }

    Damit prüfst du, ob sich ein Punkt innerhalb des Polygons befindet. Du kannst es dir so umschreiben, dass du anstatt eines IPolygons ein Point-Array übergibst, und statt dem Point2D einen Point.

    Ach und das ist übrigens die einfachste und schnellste Möglichkeit, das zu überpfrüfen, ich hab lange gesucht, als ich die Lib geschrieben hab. :D
    Ein GraphicsPath kann das von Haus aus schon. Nennt sich dort IsVisible(x,y)

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim gp As Drawing2D.GraphicsPath
    3. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    4. gp = New Drawing2D.GraphicsPath
    5. gp.AddRectangle(New Rectangle(10, 20, 33, 44))
    6. 'gp.AddPolygon (...)
    7. End Sub
    8. Private Sub Form1_MouseClick(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
    9. If gp.IsVisible(e.X, e.Y) Then
    10. Me.Text = "treffer"
    11. Else
    12. Me.Text = "daneben"
    13. End If
    14. End Sub
    15. Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    16. e.Graphics.FillPath(Brushes.Black, gp)
    17. End Sub
    18. End Class


    Edit: die Lib von dir sieht aber nice aus!
    Hi
    wär's nicht einfacher, das direkt als Bild + zusätzliches Array zu machen sofern keine auflösungsunabhängige Darstellung gebraucht wird? Der Array-Index (/die Array-Indices) werden aus der Position auf dem Bild berechnet und auf Basis des Eintrags dann halt was gemacht. Wäre wohl performanter, als Polygone. Gerade Landkarten haben nämlich einen sehr hohen Detailgrad, was dann in sehr vielen Polygonen resultieren würde (ansonsten DirectX + shader + Mipmapping ftw.).

    Gruß
    ~blaze~
    Das müsste man abwägen. Wenn der Graphicspath - egal wie komplex sein Inhalt - erstmal da ist müsste er sich schnell zeichnen lassen. Habe ich aber nicht getestet. Der Vorteil ist eben, dass man viel mit ihm anstellen kann - beim draufkicken umranden, Farbe ändern, Zoomen ohne Qualitätsverlust und Kollisionserkennug inklusive.

    Wenn das ganze anständig aufgebaut ist, Klassen etc, wäre das auf jeden Fall sehr flexibel.

    OpferKlopfer schrieb:

    ein element in einer beliebigen form zu machen?
    Was genau schwebt Dir denn vor?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!