Page 1 of 1

Poly2D - Drawing Polygons

Posted: Sat Dec 27, 2003 12:15 pm
by Christian
Hi!

I've coded some procedures to draw polygons in PB. Perhaps there is anyone who wants to use it. Unfortunataly the comments are in German. So if there are questions feel free to ask. I would also like to get some feedback. :)

Poly2D.pbi

Code: Select all

; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  *************************************************************************** ~
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
;   Polygon2D Drawing Prozeduren (ver. 1.00)
;        2003 by Christian Stolze
;
;        Mit diesen Prozeduren können relativ schnell und einfach Polygone mit
;        bliebig vielen Eckpunkten gezeichnet werden. Dies ist jedoch nur für
;        2D Zeichenoperationen möglich.
;
;        Erstellt am 26.12.2003
;
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  *************************************************************************** ~
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Procedure InitPolygonDrawing()     ; Initialisierung für die Polygonlibrary
Structure Vertex                   ; Struktur für die LinkedLists in denen VertexDaten gespeichert werden
 PID.l
 ID.l
 x.l
 y.l
EndStructure

Global NewList PolygonPoints.Vertex()     ; LinkedList zum Speichern der Vertex-Kooardinaten der Polygon-Eckpunkte
Global NewList PolygonDrawBuffer.Vertex() ; Zwischenspeicher für spätere Zeichenarbeiten

If ListSize(PolygonPoints())
 If PolygonDrawBuffer()
    result.l = PolygonPoints() + PolygonDrawBuffer()
 Else
    result.l = -1
 EndIf
Else
    result.l = -1
EndIf
ProcedureReturn result.l
EndProcedure

Procedure.l SetPolygonPoint(PolygonID.l, ID.l, x.l, y.l) ; Setzen eines Eckpunktes
ResetList(PolygonPoints())
While NextElement(PolygonPoints())
 If PolygonPoints()\ID = ID.l And PolygonPoints()\PID = PolygonID.l
     result.l = -1
 Else
     result.l = 0
 EndIf
Wend

If result <> -1                                           ; Speichert die Eckpunktdaten in die LinkedList
 AddElement(PolygonPoints())
  PolygonPoints()\PID = PolygonID.l
  PolygonPoints()\ID = ID.l
  PolygonPoints()\x = x.l
  PolygonPoints()\y = y.l
EndIf

ProcedureReturn result.l
EndProcedure

Procedure.l DeletePolygonPoint(PolygonID.l, ID.l)        ; Löscht einen Eckpunkt mit der ID.l aus dem angegebenem Polygon
 ResetList(PolygonPoints())
 While NextElement(PolygonPoints())                       ; durchsucht die LinkedList nach dem angegeben Punkt
 If PolygonPoints()\ID = ID.l And PolygonPoints()\PID = PolygonID.l
     DeleteElement(PolygonPoints())
     result.l = 0
 Else
     result.l = -1
 EndIf
Wend

ProcedureReturn result.l                                ; gibt -1 zurück, wenn der Eckpunkt nicht gelöscht werden konnte.(ansonsten 0)
EndProcedure

Procedure.l MovePolygonPoint(PolygonID.l, ID.l, NewID.l, NewX.l, NewY.l) ; ändert die Daten eines Eckpunktes (ID.l) innerhalb des Polygons (PolygonID.l)
 ResetList(PolygonPoints())
 While NextElement(PolygonPoints())                                       ; LinkedList wird nach dem Eckpunkt durchsucht
  If PolygonPoints()\ID = ID.l And PolygonPoints()\PID = PolygonID.l
      result.l = 0
      DeleteElement(PolygonPoints())                                      ; wurde er gefunden, wird er gelöscht ...
      Break
  Else
      result.l = -1
  EndIf
 Wend
 If result.l <> -1
    SelectElement(PolygonPoints(), ID.l-1)
    AddElement(PolygonPoints())                                            ; ... und nun wieder mit neuen Daten hinzugefügt
     PolygonPoints()\ID = NewID.l
     PolygonPoints()\x = NewX.l
     PolygonPoints()\y = NewY.l
 EndIf
ProcedureReturn result.l
EndProcedure

Procedure CreatePolygon(PolygonID.l, Width.l, Height.l, BorderColor.l)    ; Zeichnen eines Polygons
 Protected last.l
 Protected VertexX.l, VertexY.l, VertexX1.l, VertexY1.l, VertexX2.l, VertexY2.l

 CreateSprite(PolygonID.l, Width.l, Height.l)                              ; Sprite auf dem das Polygon gezeichnet wird, wird erstellt

 ClearList(PolygonDrawBuffer())                                            ; Zwischenspeicher wird gelöscht
 ResetList(PolygonPoints())                                                ; Alle Eckpunkte des angegeben Polygons (PolygonID.l) werden gesucht ...
 While NextElement(PolygonPoints())
   If PolygonPoints()\PID = PolygonID.l
       AddElement(PolygonDrawBuffer())                                     ; ... und in den Zwischenspeicher eingefügt
        PolygonDrawBuffer()\PID = PolygonPoints()\PID
        PolygonDrawBuffer()\ID = PolygonPoints()\ID
        PolygonDrawBuffer()\x = PolygonPoints()\x
        PolygonDrawBuffer()\y = PolygonPoints()\y
   EndIf
 Wend

;  ResetList(PolygonDrawBuffer())                                          ; kann einkommentiert werden, um die Eckpunkte
;  While NextElement(PolygonDrawBuffer())                                  ; des Polygons mit Kreisen zu markieren
;    VertexX.l = PolygonDrawBuffer()\x
;    VertexY.l = PolygonDrawBuffer()\y
;    If StartDrawing(SpriteOutput(PolygonID.l))
;        Circle(VertexX.l, VertexY.l, 5, BorderColor.l)
;       StopDrawing()
;    EndIf
;   Wend

  ResetList(PolygonDrawBuffer())                                           ; erster und damit letzten Eckpunkt wird ausgelesen und die Koordinaten gespeichert
  NextElement(PolygonDrawBuffer())                                         ; (wird zum Schluß noch gebraucht)
   VertexX.l = PolygonDrawBuffer()\x
   VertexY.l = PolygonDrawBuffer()\y

  ResetList(PolygonDrawBuffer())                                           ; nun werden nacheinander die Koordinaten der Punkte ausgelesen
  While NextElement(PolygonDrawBuffer())
    VertexX1.l = PolygonDrawBuffer()\x
    VertexY1.l = PolygonDrawBuffer()\y
    If NextElement(PolygonDrawBuffer())
        VertexX2.l = PolygonDrawBuffer()\x
        VertexY2.l = PolygonDrawBuffer()\y
        PreviousElement(PolygonDrawBuffer())
    ElseIf last.l = 0                                                      ; hier werden die Koordinaten der ersten und letzten Elementes wieder in einer weitere
        VertexX1.l = VertexX2.l                                             ; Variable gespeichert um das Polygon abzuschließen
        VertexY1.l = VertexY2.l                                             ; und somit den (vor)letzten Eckpunkt wieder mit dem ersten(/letzten)
        VertexX2.l = VertexX.l                                              ; verbinden zu können
        VertexY2.l = VertexY.l
        last.l = 1
    EndIf
    If StartDrawing(SpriteOutput(PolygonID.l))                            ; hier werden jeweils 2 Eckpunkte mit einer Linie verbunden
        LineXY(VertexX1.l, VertexY1.l, VertexX2.l, VertexY2.l, BorderColor.l)
        StopDrawing()
    EndIf
  Wend
EndProcedure

Procedure DeletePolygon(PolygonID.l)                                     ; Löscht alle Eckpunkte des angegebenen Polygons aus der LinkedList
 ResetList(PolygonPoints())
 While NextElement(PolygonPoints())
   If PolygonPoints()\PID = PolygonID.l
       DeleteElement(PolygonPoints())
   EndIf
 Wend
EndProcedure

Procedure SetPolygonColor(PolygonID.l, x.l, y.l, OutlinColor.l, Color.l) ; Füllt das angegebene Polygon vom Punkt x,y aus mit der Farbe Color.l bis die
 If StartDrawing(SpriteOutput(PolygonID.l))                               ; bis die Randfarbe (OutlinColor.l) auftritt
     FillArea(x.l, y.l, OutlinColor.l, Color.l)
     StopDrawing()
 EndIf
EndProcedure

Procedure DisplayPolygon(PolygonID.l, x.l, y.l)                          ; Zeigt das angegebene Polygon(/Sprite) auf dem Bildschirm an
 DisplaySprite(PolygonID.l, x.l, y.l)
EndProcedure

Procedure DisplayTransparentPolygon(PolygonID.l, x.l, y.l, Red.l, Green.l, Blue.l) ; Zeigt das angegebene Polygon(/Sprite) auf dem Bildschirm an
 TransparentSpriteColor(PolygonID.l, RGB(Red.l, Green.l, Blue.l))                        ; wobei die angegebene Farbe Transparent dargestellt wird
 DisplayTransparentSprite(PolygonID.l, x.l, y.l)
EndProcedure

Procedure.l GetPolygonPointX(PolygonID.l, ID.l)                         ; Ausgabe der X-Koordinate eines Eckpunktes
 ResetList(PolygonPoints())
 While NextElement(PolygonPoints())                                       ; LinkedList wird nach dem Eckpunkt durchsucht
  If PolygonPoints()\ID = ID.l And PolygonPoints()\PID = PolygonID.l
      result.l = PolygonPoints()\x
      Break
  Else
      result.l = -1
  EndIf
 Wend
ProcedureReturn result.l
EndProcedure

Procedure.l GetPolygonPointY(PolygonID.l, ID.l)                         ; Ausgabe der Y-Koordinate eines Eckpunktes
 ResetList(PolygonPoints())
 While NextElement(PolygonPoints())                                       ; LinkedList wird nach dem Eckpunkt durchsucht
  If PolygonPoints()\ID = ID.l And PolygonPoints()\PID = PolygonID.l
      result.l = PolygonPoints()\y
      Break
  Else
      result.l = -1
  EndIf
 Wend
ProcedureReturn result.l
EndProcedure
And a small example for you:

Code: Select all

XIncludeFile "Poly2D.pbi"

#SCREEN_Width = 500
#SCREEN_Height = 500

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
   MessageRequester("ERROR","Cant init DirectX",0)
   End
EndIf

MainWnd.l = OpenWindow(0, 0, 0, #SCREEN_Width, #SCREEN_Height, "Polygon Beispiel", #PB_Window_ScreenCentered)
If OpenWindowedScreen(MainWnd.l, 0, 0, #SCREEN_Width, #SCREEN_Height, 1, 0, 0)

 If InitPolygonDrawing()
; -- Cursor
  SetPolygonPoint(0, 0,   5,   5)
  SetPolygonPoint(0, 1,  30,  20)
  SetPolygonPoint(0, 2,  17,  17)
  SetPolygonPoint(0, 3,  20,  30)

  CreatePolygon(0, 50, 50, RGB(0,0,255))
  SetPolygonColor(0, 10, 10, RGB(0,0,255), RGB(0,0,255))

; -- Fünfeck
  SetPolygonPoint(1, 0,   0,   0)
  SetPolygonPoint(1, 1, 150,   0)
  SetPolygonPoint(1, 2, 175,  75)
  SetPolygonPoint(1, 3, 150, 200)
  SetPolygonPoint(1, 4,  50, 125)

  CreatePolygon(1, 176, 201, RGB(255,255,255))
  SetPolygonColor(1, 10, 10, RGB(255,255,255), RGB(255,0,0))

; -- Dreieck
  SetPolygonPoint(2, 0,   0,  25)
  SetPolygonPoint(2, 1, 150,   0)
  SetPolygonPoint(2, 2, 175,  75)

  CreatePolygon(2, 176, 76, RGB(255,0,255))

; -- Achteck
  SetPolygonPoint(3, 0,  50,  50)
  SetPolygonPoint(3, 1, 100,  25)
  SetPolygonPoint(3, 2, 150,  50)
  SetPolygonPoint(3, 3, 175, 100)
  SetPolygonPoint(3, 4, 150, 150)
  SetPolygonPoint(3, 5, 100, 175)
  SetPolygonPoint(3, 6,  50, 150)
  SetPolygonPoint(3, 7,  25, 100)

  CreatePolygon(3, 176, 176, RGB(255,255,0))
  SetPolygonColor(3, 51, 51, RGB(255,255,0), RGB(255,255,0))
 EndIf

EndIf

a.l = -1
b.l = -1

Repeat
While WindowEvent() : Wend
ExamineKeyboard()
ExamineMouse()

DisplayPolygon(1, 250, 200)                               ; Fünfeck
DisplayTransparentPolygon(2, 20, 20, 0, 0, 0)             ; Dreieck     -> Schwarz als transparente Farbe
DisplayTransparentPolygon(3, 20, 250, 0, 0, 0)            ; Achteck     -> Schwarz als transparente Farbe
DisplayTransparentPolygon(0, MouseX(), MouseY(), 0, 0, 0) ; Mousecursor -> Schwarz als transparente Farbe


FlipBuffers()
ClearScreen(RGB(0, 0, 0))
Until KeyboardPushed(#PB_Key_Escape)
End
Best regards,
Christian

_____________________________________

Edit - Added:
· GetPolygonPointX() - 27.12.03
· GetPolygonPointY() - 27.12.03

Posted: Sat Dec 27, 2003 3:16 pm
by Christian
Hi again!

I've added two new procedures and fixed a bug in the MovePolygonPoint()-procedure.

Best regards,
Christian

Posted: Wed May 12, 2004 7:34 pm
by J. Baker
Just tried to compile in PB 3.90 and I don't fully understand what's wrong with the current procedure on line 177 of the pbi file?

Posted: Wed May 12, 2004 8:08 pm
by fweil
...,

Just replace lines 177 and 190 from :

Code: Select all

Procedure.l = GetPolygonPointX(PolygonID.l, ID.l)                         ; Procedure.l = GetPolygonPointY(PolygonID.l, ID.l)                         ; 
to :

Code: Select all

Procedure.l GetPolygonPointX(PolygonID.l, ID.l)                         ; Procedure.l GetPolygonPointY(PolygonID.l, ID.l)                         ; 
It will work.

Posted: Wed May 12, 2004 9:17 pm
by J. Baker
Thanks :D

Re: Poly2D - Drawing Polygons

Posted: Sun Feb 24, 2013 8:40 am
by SiriusMonk
Problem with line 42 PolgonPoints() is not a function, array, macro or linked list ?

Could somebody solve or explain how to fix this. Thanks in advance.

Regards SiriusMonk


Purebasic 5.10 (final) , Windows 7 pre

Re: Poly2D - Drawing Polygons

Posted: Sun Feb 24, 2013 12:10 pm
by Fred
I just updated the first first for v5.10.