Object2D Class


In the previous example, I introduced a subclass of Object2Dthe PixmapShape class. Although that class was used to display a raster graphic, the primary function provided by the Object2D classes is for manipulating vector images. The PixmapShape class allows you to create more complex images that include both raster and vector images, something that is not uncommon at all.

The Object2D subclasses are really the best way to handle any kind of complex drawing, regardless of where it will be displayed. The parent class provides methods for scaling and rotating the image, as well as whether to place a border around it and what the fill color should be.

Object2D.Border as Double Object2D.BorderColor as Color Object2D.BorderWidth as Double Object2D.Fill as Double Object2D.FillColor as Color


All objects can be rotated by setting the following property:

Object2D.Rotation as Double


The rotation is measured in radians, not in degrees, which is what you might have expected. A radian is an arc whose length is equal to its radius and there are exactly 2p radians in a circle. Figure 10.7 illustrates how far a one radian is:

Figure 10.7. A radian is an arc whose length is equal to its radius.


To see a more detailed explanation of how to use radians, review the example in the ArcShape section.

In addition to rotating shapes, you can also resize them using the following:

Object2D.Scale as Double


Scale takes a Double value, which it interprets as a percentage. Therefore, .5 is the equivalent to scaling the image to 50% of the original size. Scaling the image to a value of 50 means 500% the original size.

All Object2D instances have an X and a Y property, indicating the position where the Object2D instance will be drawn, relative to the center of the object.

Object2D.X as Double Object2D.Y as Double


PixmapShape

In addition to the properties and methods of the parent Object2D class, the PixmapShape implements the following. First, the property that contains a reference to the Picture object associated with the PixmapShape instance:

PixmapShape.Image as Picture


The following properties allow you to define a subregion of the original picture. The first two are a measure of how many pixels away from the left and top edges of the original image the subimage is:

PixmapShape.SourceLeft as Integer PixmapShape.SourceTop as Integer


This is followed by two properties that define the overall height and width of the subimage:

PixmapShape.SourceHeight as Integer PixmapShape.SourceWidth as Integer


When instantiating a PixmapShape, pass the Picture in the Constructor:

PixmapShape.Constructor(Image as Picture)


RectShape

The RectShape is one of the easiest shapes to handle. The Object2D properties X and Y define the center point of the rectangle, and the following properties determine how tall and wide it is:

RectShape.Height as Double RectShape.Width as Double


One interesting feature in addition is the Contains method, which allows you to test a point to see if it is within a particular RectShape:

RectShape.Contains(X as Double, Y as Double) as Boolean


One way that you might use this would be to test to see whether the mouse position is over a particular RectShape and then respond when it is moved over the RectShape, or if the RectShape is clicked.

RoundRectShape Inherits RectShape

A RoundRectShape is just like a RectShape, except that the corners are rounded. You adjust the point where the curve starts on each corner with the following properties:

RoundRectShape.Cornerheight as Double RoundRectShape.Cornerwidth as Double


The following determines how smooth the curves are (see the OvalShape explanation):

RoundRectShape.Segments as Integer


OvalShape Inherits RectShape

The OvalShape is a subclass of RectShape and behaves just like a RectShape in all ways. The only addition is the following property:

OvalShape.Segments as Integer


Even though you see a circular shape when you look at an OvalShape on your computer screen, the underlying rendering engine is actually drawing a polygon and not a circle. When you set the value of Segments, you are telling REALbasic how many sides the polygon should have. The more sides it has, the smoother the curve appears on the screen.

ArcShape Inherits OvalShape

Drawing an ArcShape requires the use of two different angles, measured in radians:

ArcShape.ArcAngle as Double ArcShape.StartAngle as Double


The start angle is the location on the circle where the arc begins, and the arc angle is the size of the arc. Figure 10.8 shows an arc whose StartAngle is 0, and whose ArcAngle is 1:

Figure 10.8. An ArcShape of one radian.


In a moment I'll share the code that generated this screenshot, but there are a few pieces of information that will help you make sense of it. As I said earlier, there are 2p radians in one circle. The value of p is

3.14159265358979323846264338327950


Keeping this in mind, that means there are 6.28318530718 radians in one circle. If you want to convert from radians to degrees, you can use the following formula:

degrees = radians*(180/p)


Likewise, if you want to convert degrees to radians, you can use this formula:

radians = degrees/(180/p)


This means that 1 degree is approximately equivalent to 0.0174533 radians, and 1 radian is approximately 57.29578 degrees. Now you can turn to the sample code and follow along.

Listing 10.8. PushButton1.Action Handles Event

Dim rad as Double Dim arc as ArcShape Dim p as Picture Const pi  = 3.14159265358979323846264338327950 // Get the number of radians from EditField1 rad = Val(EditField1.Text) // Convert Radians to Degrees and display it // in EditField2 EditField2.Text = Str(rad*(180/pi)) p = NewPicture(Window1.Canvas1.Height, Window1.Canvas1.Width, 24) arc = New ArcShape arc.Width = 100 arc.Height = 100 // A StartAngle of 0 starts the arc at 45 degrees arc.StartAngle = 0 // This arc will be one radian arc.ArcAngle = rad // Setting the Segments property makes the curve // be drawn more smoothly on the screen. I have // this set to a relatively high value. arc.Segments = 360 // Set the color to red. arc.FillColor = RGB(255, 5, 5) // Create the Picture object p.Graphics.DrawObject arc, Canvas1.Height/2, Canvas1.Width/2 // Display the Picture object in the Canvas1 control Window1.Canvas1.Graphics.DrawPicture p, 0, 0

In this code, I am displaying an ArcShape of only one radian. You may be wondering how to display an ArcShape of 360 degrees, given the fact that there are 6.282185 radians in a circle. If you take this code and plug in 6.282175 into EditField1 and click the Show button, you will see that nothing gets drawn. If you increase the value to 6.5, you will see a little sliver of an ArcShapewith a measure of about 0.2168 radians, which is the value of 6.5 minus 6.282175. To draw a complete circle, you should plug in the value 6.283184.

StringShape

The StringShape class draws text, but in a fairly limited way. It does not support text with line breaks in it, and you can't do things such as measure the width of the text or automatically wrap it like you can when using a Graphics object. The intended use for the class is to display text inside a vector image. It is not intended as a general-purpose text-rendering class or anything like that.

You can set the following properties:

StringShape.Text as String StringShape.TextFont as String StringShape.TextSize as Double StringShape.Underline as Boolean StringShape.Bold as Boolean StringShape.Italic as Boolean


CurveShape

The CurveShape is a class for drawing Bezier curves. The basic information you need to know about Bezier curves are that there are three types: Linear, Quadratic, and Cubic. A Linear Bezier curve can be defined by two points and is a straight line. A Quadratic Bezier curve requires three points and represents a curve drawn through all three points. A Cubic Bezier curve requires four points to draw, and an example is given later in this chapter.

You set the type of Bezier curve to draw using the following property:

CurveShape.Order as Integer


The values are as follows:

Linear Bezier Curve: 0 Quadratic Bezier Curve: 1 Cubic Bezier Curve: 2


Like all Object2D subclasses, a CurveShape has values for X and Y and adds to that values for X2 and Y2:

CurveShape.X as Double CurveShape.Y as Double CurveShape.X2 as Double CurveShape.Y2 as Double


These properties are sufficient to draw a Linear Bezier curve, but you will need some additional points if you are drawing a Cubic or Quadratic Bezier curve:

CurveShape.ControlX(Index as Integer) as Double CurveShape.ControlY(Index as Integer) as Double


Both properties are indexed, and the value for the index can be either 0 or 1. If you are drawing a Quadratic Bezier curve, you need only one more set of control points, and you can refer to them like this:

CurveShape1.ControlX(0) = 10 CurveShape1.ControlY(0) = 25


If you are drawing a Cubic Bezier curve you need one more additional point, which can be referenced in this manner:

CurveShape1.ControlX(1) = 10 CurveShape1.ControlY(1) = 25


Finally, just like the OvalShape, you can set the value of following to make the curve get drawn more smoothly (the higher the value, the smoother the curve):

CurveShape.Segments as Integer


FigureShape

A FigureShape is a collection of CurveShapes. As such, it provides methods for adding curves and removing and referencing them by index. These work just like the array functions.

FigureShape.Count as Integer FigureShape.Item(Index as Integer) as CurveShape FigureShape.Append(Curve as CurveShape) FigureShape.Insert(Index as Integer, Curve as CurveShape) FigureShape.Remove(Index as Integer) FigureShape.Remove(Curve as CurveShape)


It also provides methods for drawing Linear, Quadratic, and Bezier curves that are a little simpler to use than those required in the CurveShape class.

[View full width]

FigureShape.AddLine(X as Integer, Y as Integer, X2 as Integer, Y2 as Integer) FigureShape.AddQuad(X as Integer, Y as Integer, X2 as Integer, Y2 as Integer, CX as Integer, CY as Integer) FigureShape.AddCubic(X as Integer, Y as Integer, X2 as Integer, Y2 as Integer, CX as Integer, CY as Integer, CX2 as Integer, CY2 as Integer)


Group2D

Whereas a FigureShape is a collection of CurveShapes, a Group2D is a collection of any kind of Object2D subclass.

Group2D.Count as Integer Group2D.Item(Index as Integer) as Object2D Group2D.Append(Object as Object2D) Group2D.Insert(Index as Integer, Object as Object2D) Group2D.Remove(Index as Integer) Group2D.Remove(Object as Object2D)


A FigureShape Example

The following example illustrates how to use several of the Object2D subclasses. Most importantly, it illustrates one of the methods of the FigureShape class that can be difficult to understand how to use unless you actually see it at work. The FigureShape class is used to draw collections of curves, and it contains a few methods for displaying Bezier curves. This example illustrates a Cubic Bezier curve.

You need to set four different points to describe a cubic curve, and this means passing eight values to the AddCubic method. The first group sets the starting point of the curve, and the second two set the end point of the curve. At this point, if the rest of the values are set to zero, you have a line. The final four arguments set two additional points, which makes the line curve. Altogether there are four points set that form a quadrilateral, and the curve is constrained to stay within the space defined by the quadrilateral. The only way to really understand how the final two points that get set impact the shape of the curve is to see what happens as you adjust them, and that is what this project does.

There are eight Sliders, one for each of the arguments. When the application starts, you can move the Sliders back and forth and see how the curve changes as the values change. Each point is illustrated with a dot, plus text that identifies what the actual values are. The curve adjusts in real-time as the Sliders are drawn, so double buffering is a requirement to minimize or eliminate any screen flicker, but it also serves a more mundane purpose. If I do not create a new Picture object for each new state, the next curve just gets redrawn on top of the previous curvethe old curve is not deleted. By using double buffering, the previous line is not preserved and you get a more seamless visual representation.

The actual application is quite simple. There's one method associated with Window1 that gets called by each Slider control whenever the ValueChanged event is triggered. The method is called DrawPict, and it looks like this:

Listing 10.9. DrawPict MethodDim p as Picture

[View full width]

Dim aGroup as Group2D Dim aString as StringShape Dim aFigure as FigureShape Dim aRect as RectShape aGroup = New Group2D aFigure = New FigureShape aFigure.FillColor = RGB(100,100,100) aFigure.BorderColor = RGB(80,80,80) aFigure.AddCubic(Slider1.Value, Slider2.Value, Slider3.Value, Slider4.Value, Slider5.Value , Slider6.Value, Slider7.Value, Slider8.Value) // The points are identified by drawing a small // rectangle using different colors. The first // point is the starting point of the curve and // the color is set to be red and the actual // position is set by the values in Slider1 and Slider2 aRect = new RectShape aRect.FillColor = RGB(255,0,0) aRect.Height = 4 aRect.Width = 4 aRect.X = Slider1.Value aRect.Y = Slider2.Value // Each point is labeled and the text is drawn // using the StringShape class. aString = new StringShape aString.Text = "(X: " + Str(aRect.X) + ", Y:" + Str(aRect.Y) + ")" aString.X = aRect.X // The String is positioned below the rectangle so that // the rectangle is clearly visible. aString.Y = aRect.Y+12 // Next, the FigureShape,RectShape and StringShape objects // are added to a Group2D object. aGroup.Append(aFigure) aGroup.Append(aRect) aGroup.Append(aString) // Now, the process repeats itself with the // next set of points that indicate where the // line starts. aRect = New RectShape aRect.FillColor = RGB(125, 0, 0) aRect.Height = 4 aRect.Width = 4 aRect.X = Slider3.Value aRect.Y = Slider4.Value aString = new StringShape aString.Text = "(X1: " + Str(aRect.X) + ", Y1:" + Str(aRect.Y) + ")" aString.X = aRect.X aString.Y = aRect.Y+12 aGroup.Append(aRect) aGroup.Append(aString) // The next point get set. // This is the equivalent of // ControlX(0) and ControlY(0) // in the CurveShape class. aRect = New RectShape aRect.FillColor = RGB(0, 255, 0) aRect.Height = 4 aRect.Width = 4 aRect.X = Slider5.Value aRect.Y = Slider6.Value aString = new StringShape aString.Text = "(CX: " + Str(aRect.X) + ", CY:" + Str(aRect.Y) + ")" aString.X = aRect.X aString.Y = aRect.Y+12 aGroup.Append(aRect) aGroup.Append(aString) // The final point gets set // This is the equivalent of // ControlX(1) and ControlY(1) // in the CurveShape class. aRect = New RectShape aRect.FillColor = RGB(0, 0, 255) aRect.Height = 4 aRect.Width = 4 aRect.X = Slider7.Value aRect.Y = Slider8.Value aString = new StringShape aString.Text = "(CX2: " + Str(aRect.X) + ", CY2:" + Str(aRect.Y) + ")" aString.X = aRect.X aString.Y = aRect.Y +12 aGroup.Append(aRect) aGroup.Append(aString) // Instantiate a Picture object that is the same // size as the Canvas object, with a color depth of // 32 bits. p = NewPicture(canvas1.width,canvas1.height, 32) // Draw the Group2D object into the Picture using // the Graphics object's DrawObject method p.Graphics.DrawObject(aGroup, 0,0) // Next, draw the buffered picture into // Canvas1's Graphics object. Canvas1.Graphics.DrawPicture(p,0,0) 

In Figure 10.9, you can see an example of a Cubic Bezier curve as rendered by the previous code. Because the rendering is buffered, you can move each slider to the left and see the Cubic Bezier curve to the right get updated immediately.

Figure 10.9. FigureShape example.





REALbasic Cross-Platform Application Development
REALbasic Cross-Platform Application Development
ISBN: 0672328135
EAN: 2147483647
Year: 2004
Pages: 149

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net