Author Topic: FB Graphics #3: The Point Object  (Read 3964 times)

0 Members and 1 Guest are viewing this topic.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
FB Graphics #3: The Point Object
« on: September 24, 2009 »
Introduction

Now that the screen object has a robust color object, we need to add some graphic primitive, such as a point, line, circle, rectangle and polygon. We will start with the point, since it is the basic graphic primitive that all the other primitives share. In keeping with the object theme, in this tutorial we will create a point object that we can use as the basis for all the other primitives.

Private Data

The following code snippet lists the point objects private data section.

Code: [Select]
Type pntobj2D

Private:
_pntx As Integer  'X coord of point.
_pnty As Integer  'Y coord of point.
_pntclr As clrobj 'The color of the point.
_pi As Double     'Value of pi.

The _pntx and _pnty variables contain the screen coordinates of the point. _pntclr is a color object that contains the current point color. _pi is initialzed within each Constructor and is used in the Rotate2D function, which we will examine shortly. Even though the data section is quite short, this is everything we need to know about a point on the screen.

The Constructors

Code: [Select]
Public:
Declare Constructor () 'No arg constructor.
Declare Constructor (x As Integer, y As Integer, clr As clrobj)   'Using color object.
Declare Constructor (x As Integer, y As Integer, clr As UInteger) 'Using color value.
Declare Constructor (pnt As pntobj2D) 'Constructor using point object.

'No arg constructor.
Constructor pntobj2D ()
'Set default values for point object.
_pntx = 0
_pnty = 0
_pntclr.ColorValue = RGBA(0, 0, 0, 255)
_pi = Atn ( 1.0 ) * 4
End Constructor

'Constructor using color object.
Constructor pntobj2D (x As Integer, y As Integer, clr As clrobj)
_pntx = x
_pnty = y
_pntclr = clr
_pi = Atn ( 1.0 ) * 4
End Constructor

'Constructor using color value.
Constructor pntobj2D (x As Integer, y As Integer, clr As UInteger)
_pntx = x
_pnty = y
_pntclr.ColorValue = clr
_pi = Atn ( 1.0 ) * 4
End Constructor

'Constructor using point object.
Constructor pntobj2D (pnt As pntobj2D)
_pntx = pnt.PointX
_pnty = pnt.PointY
_pntclr = pnt.ColorObj
_pi = Atn ( 1.0 ) * 4
End Constructor

As you can see, the constructors are quite straightforward and should look familiar by now. You may ask though, why have a no arg constructor when a point needs to have a specific value? We will use the no arg constructor when we declare the point object in the other graphic primitives, such as the line. We could declare a pointer and then use the New function to create a reference to the point object. New allows you to initialize the object through a constructor, but then you run into the problem of making sure references are deleted which adds to the code and isn't really necessary in this case. We will always make sure the point object is properly initialized through the exposed properties when using it within the other graphic primitives.

Properties

Code: [Select]
Declare Property PointX (x As Integer) 'Sets the x coord.
Declare Property PointX () As Integer 'Returns the x coord.
Declare Property PointY (y As Integer) 'Sets the y coord.
Declare Property PointY () As Integer 'Returns the y coord.
Declare Property PointColor (clr As UInteger) 'Sets color using color value.
Declare Property PointColor (clr As clrobj) 'Sets color using color object.
Declare Property ChannelAlpha () As UByte'Return alpha channel.
Declare Property ChannelAlpha (a As UByte) 'Set red channel.

'Sets the x coord.
Property pntobj2D.PointX (x As Integer)
_pntx = x
End Property

'Returns the x coord.
Property pntobj2D.PointX () As Integer
Return _pntx
End Property

'Sets the y coord.
Property pntobj2D.PointY (y As Integer)
_pnty = y
End Property

'Returns the y coord.
Property pntobj2D.PointY () As Integer
Return _pnty
End Property

'Sets color using color value.
Property pntobj2D.PointColor (clr As UInteger)
_pntclr.ColorValue = clr
End Property

'Sets color using color object.
Property pntobj2D.PointColor (clr As clrobj)
_pntclr = clr
End Property

'Set alpha channel.
Property pntobj2D.ChannelAlpha (a As UByte)
_pntclr.ChannelAlpha = a
End Property

'Return alpha channel.
Property pntobj2D.ChannelAlpha () As UByte
Return _pntclr.ChannelAlpha
End Property

The property format should also look familiar by now. The PointX and PointY properties set and return the current X and Y of the point. The color of the point can be changed, either through using a color value or color object. The Alpha channel may seem odd, but it is necessary for use in the PokeAlpha procedure of the screen object, which we will examine shortly.

Functions

There are two functions in the point object, and both return the color of the object, either as a color value or color object. These are needed for the Poke* functions in the screen object to write the point to the screen buffer.

Code: [Select]
Declare Function ColorValue () As UInteger'Returns color using color value.
Declare Function ColorObj () As clrobj 'Returns color using color object.

'Returns color using color value.
Function pntobj2D.ColorValue () As UInteger
Return _pntclr.ColorValue
End Function

'Returns color using color object.
Function pntobj2D.ColorObj () As clrobj
Dim tmp As clrobj

tmp = _pntclr

Return tmp
End Function

Subroutines

There are also two subroutines, both of which rotate the point object around a selected X and Y screen coordinate.

Code: [Select]
Declare Sub Rotate2D (rotpnt As pntobj2D, angle As Double)'Rotates a point around rotpoint.
Declare Sub Rotate2D (x As Integer, y As Integer, angle As Double)'Rotates a point around x, y.

'Rotates a point around rotpoint.
Sub pntobj2D.Rotate2D (rotpnt As pntobj2D, angle As Double)
Dim As Double rad = angle * _pi / 180
Dim As Double cosphi = Cos(rad), sinphi = Sin(rad)
Dim As Integer rx = _pntx - rotpnt.PointX, ry = _pnty - rotpnt.PointY

_pntx = rotpnt.PointX + rx * cosphi - ry * sinphi
_pnty = rotpnt.PointY + rx * sinphi + ry * cosphi

End Sub

'Rotates a point around x, y
Sub pntobj2D.Rotate2D (x As Integer, y As Integer, angle As Double)
Dim As Double rad = angle * _pi / 180
Dim As Double cosphi = Cos(rad), sinphi = Sin(rad)
Dim As Integer rx = _pntx - x, ry = _pnty - x

_pntx = x + rx * cosphi - ry * sinphi
_pnty = y + rx * sinphi + ry * cosphi

End Sub

The only difference between the two subroutines is that the first takes a point object, and the second takes a discrete X and Y value. Both take an angle (in degrees) of the rotation. The rotation formula is the standard formula for rotating around a point and is explained in numerous tutorials that you can find with a bit of Googling.

Operators

The point object also has a few operators that all deal with transforming the point's location on the screen, except for the Let operator which is the standard assignment operator.

Code: [Select]
Declare Operator Let (pnt As pntobj2D) 'Assignment operator.
Declare Operator += (rhs As Integer) 'Addition-assignment operator.
Declare Operator -= (rhs As Integer) 'Subtraction-assignment operator.
Declare Operator += (rhs As pntobj2D) 'Addition-assignment operator.
Declare Operator -= (rhs As pntobj2D) 'Subtraction-assignment operator.

'Assign point using object.
Operator pntobj2D.Let (pnt As pntobj2D)
_pntx = pnt.PointX
_pnty = pnt.PointY
_pntclr = pnt.ColorObj
End Operator

'Subtraction operator. Translates coords to origin.
Operator - (lhs As pntobj2D, rhs As Integer) As pntobj2D
Dim tmp As pntobj2D

tmp.PointX = lhs.PointX - rhs
If tmp.PointX < 0 Then tmp.PointX = 0
tmp.PointY = lhs.PointY - rhs
If tmp.PointY < 0 Then tmp.PointY = 0

Return tmp
End Operator


'Addition operator. Translates coords away from origin.
Operator + (lhs As pntobj2D, rhs As Integer) As pntobj2D
Dim tmp As pntobj2D

tmp.PointX = lhs.PointX + rhs
tmp.PointY = lhs.PointY + rhs

Return tmp
End Operator

'Subtraction operator. Adds two points.
Operator - (lhs As pntobj2D, rhs As pntobj2D) As pntobj2D
Dim tmp As pntobj2D

tmp.PointX = lhs.PointX - rhs.PointX
If tmp.PointX < 0 Then tmp.PointX = 0
tmp.PointY = lhs.PointY - rhs.PointY
If tmp.PointY < 0 Then tmp.PointY = 0

Return tmp
End Operator

'Addition operator. Subtracts two points.
Operator + (lhs As pntobj2D, rhs As pntobj2D) As pntobj2D
Dim tmp As pntobj2D

tmp.PointX = lhs.PointX + rhs.PointX
tmp.PointY = lhs.PointY + rhs.PointY

Return tmp
End Operator

'Addition-assignment operator.
Operator pntobj2D.+= (rhs As Integer)
_pntx += rhs
_pnty += rhs
End Operator

'Subtraction assignment operator.
Operator pntobj2D.-= (rhs As Integer)
_pntx -= rhs
If _pntx < 0 Then _pntx = 0
_pnty -= rhs
If _pnty < 0 Then _pnty = 0
End Operator

'Addition-assignment operator.
Operator pntobj2D.+= (rhs As pntobj2D)
_pntx += rhs.PointX
_pnty += rhs.PointY
End Operator

'Subtraction assignment operator.
Operator pntobj2D.-= (rhs As pntobj2D)
_pntx -= rhs.PointX
If _pntx < 0 Then _pntx = 0
_pnty -= rhs.PointY
If _pnty < 0 Then _pnty = 0
End Operator

As we have seen before the assignment operators can be defined within the object's definition, but the addition and subtraction operators must be defined globally. All of the operators, with the exception of the Let operator, only adjust the points coordinates, and work on both coordinates at the same time.

The operators that have the rhs values as integers, will translate the point along the diagonal axis of the screen, since both coordinates are transformed by the same amount. The operators that take a point object, can translate the point to any position on the screen, depending on the X and Y values of the point object. There is of course the option to transform a point by setting the individual PointX and PointY properties to appropriate values.

New Screen Object Routines

Now that we have a point object, we must get that point displayed on the screen, so the screen object has been updated with some routines to display a point.

Code: [Select]
Declare Sub PokeBuffer (ByRef pnt As pntobj2D) 'Sets the x and y location of buffer using point object.
Declare Sub PokeAlpha (ByRef pnt As pntobj2D) 'Sets the x and y location of buffer using point object.

'Sets the x and y location of buffer uisng point object..
Sub screenobject.PokeBuffer (ByRef pnt As pntobj2D)
'Make sure the object was initialized.
If _initok = TRUE Then
If (pnt.PointX >= 0) And (pnt.PointY >= 0) And (pnt.PointX < _width) And (pnt.PointY < _height) Then
_buffer[pnt.PointY * _width + pnt.PointX] = pnt.ColorValue
EndIf
End If
End Sub

'Sets the x and y location of buffer using point object.
Sub screenobject.PokeAlpha (ByRef pnt As pntobj2D)
Dim As UInteger bc, cc
Dim al As UByte

'Make sure the object was initialized.
If _initok = TRUE Then
If (pnt.PointX >= 0) And (pnt.PointY >= 0) And (pnt.PointX < _width) And (pnt.PointY < _height) Then
'Get the current buffer value.
bc = _buffer[pnt.PointY * _width + pnt.PointX]
'Get the alpha value.
al = pnt.ChannelAlpha
'Get the alpha blended color.
cc = _AlphaBlend (al, pnt.ColorValue, bc)
_buffer[pnt.PointY * _width + pnt.PointX] = cc
EndIf
End If

End Sub

The only changes in these new subroutines, which are just copies of the existing subroutines, is getting the X, Y and color values from the point object. Everything else is the same.

The new code can be found in this topic here. The code includes the point object and updated screen object, along with a test program.

Summary

Even though the point object is quite simple, both conceptually and in the code, it is extremely important as the foundation of all the other graphic primitives we will implement. A line and a rectangle, for example, can be defined by two points, a circle by a point and a radius and a complex polygon by a series of points. By placing the translation and rotation methods in the points itself, we can translate or rotate any of the primitives by simply translating or rotating the points of the primitive. This will give us a consistent method in dealing with the graphic primitives, and make implementing even complex polygons much easier.


Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17412
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: FB Graphics #3: The Point Object
« Reply #1 on: November 06, 2009 »
Added to front page :)
Shockwave ^ Codigos
Challenge Trophies Won: