Poly2D - Drawing Polygons

Share your advanced PureBasic knowledge/code with the community.
Christian
Enthusiast
Enthusiast
Posts: 154
Joined: Mon Dec 08, 2003 7:50 pm
Location: Germany

Poly2D - Drawing Polygons

Post 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
Christian
Enthusiast
Enthusiast
Posts: 154
Joined: Mon Dec 08, 2003 7:50 pm
Location: Germany

Post by Christian »

Hi again!

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

Best regards,
Christian
User avatar
J. Baker
Addict
Addict
Posts: 2181
Joined: Sun Apr 27, 2003 8:12 am
Location: USA
Contact:

Post 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?
www.posemotion.com

PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef


Even the vine knows it surroundings but the man with eyes does not.
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post 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.
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
User avatar
J. Baker
Addict
Addict
Posts: 2181
Joined: Sun Apr 27, 2003 8:12 am
Location: USA
Contact:

Post by J. Baker »

Thanks :D
www.posemotion.com

PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef


Even the vine knows it surroundings but the man with eyes does not.
SiriusMonk
New User
New User
Posts: 1
Joined: Fri Sep 14, 2012 8:27 am

Re: Poly2D - Drawing Polygons

Post 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
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Poly2D - Drawing Polygons

Post by Fred »

I just updated the first first for v5.10.
Post Reply