|

Drawing grids, Bézier Curves and Elliptical Arcs Using Java and SVG
By Richard G. Baldwin
Java Programming Notes # 2220
Preface
Although Bézier is the proper spelling of Pierre Bézier's name,
the use of the special character as the second character in the name makes it
very difficult to compose text using a standard computer keyboard. The name
will appear dozens of times in this lesson.
Therefore, to make it easier to compose the remainder of this tutorial, I will
take the liberty of spelling it Bezier.
Part of a series
This lesson is part of a series (see Resources)
with the following major objectives:
- To teach you how to write Java code that will produce SVG/XML output,
which can be rendered in graphic form by an SVG graphics engine such as
Firefox 1.5.
- To teach you how to write servlets that will produce SVG/XML output,
which can be rendered in graphic form by an SVG-capable browser such as
Firefox 1.5.
What you have learned
In previous lessons, you have learned:
- How to write Java code that will deposit SVG/XML code into an
output file that I refer to as an SVG file.
- How to write Java code that will deposit in-line SVG code
into an XHTML file.
- How to write Java servlet code that will deposit in-line SVG
code into XHTML code in the servlet's output data stream.
- How to write Java code that will create an output XHTML file
that references an external SVG file.
- How to write Java servlet code that will create an output
XHTML data stream that references an external SVG file.
- How to write a Java/SVG graphics library that removes much of
the pain from writing Java code to produce SVG/XML output.
- How to program and use many of the features of SVG to produce
rich graphics in an SVG-capable browser window.
The servlet objective has been satisfied
At this point, I believe that I have satisfied the second objective listed
above involving servlets. However, even though I have taught you a lot about the
many features of SVG, there are other important features that I have not yet
covered. Therefore, the first objective listed above has not
yet been
satisfied.
Will assume that you understand SVG/servlet code in
general
Beginning with this lesson, most of the remaining lessons in this series will
assume that once you understand how to write Java code to implement a particular
SVG feature, you will already understand how to incorporate that Java code into
a servlet such that the output data stream from the servlet will deposit that
SVG code into an XHTML data output stream. Consequently, I will have
little to say about servlets in the remaining lessons in the series, and will
concentrate on helping you to understand how to write the Java code necessary to
take advantage of various SVG features. Typically, the sample programs
will produce output SVG files that can be rendered in graphic form by an SVG
graphics engine such as Firefox 1.5.
What you will learn in this lesson
In this lesson you will learn how to write Java code that uses an SVG
graphics library and the SVG path element to efficiently draw grid
lines, geometric shapes, cubic Bezier curves,
quadratic Bezier curves, and elliptical arcs.
An SVG graphics library
In earlier lessons, I taught you how write your own Java
SVG graphics library to eliminate, or at least alleviate the requirement to
write raw XML code or raw JAXP DOM code. The use of the SVG graphics library
makes it possible for you to produce SVG output simply by making typical Java
method calls. I updated my version of the Java SVG graphics library to
contain several new methods for use in this lesson.
I recommend that you open another copy of this document in a separate browser
window and use the following links to easily find and view the figures and
listings while you are reading about them.
- Figure 1. The graphic output from the program.
- Figure 2. Sample cubic Bezier curves.
- Figure 3. Sample d attribute value for a
cubic Bezier curve.
- Figure 4. Combinations of large-arc-flag and
sweep-flag.
- Figure 5. A portion of the SVG/XML code for the
grid.
- Figure 6. A text element.
- Figure 7. XML code for the red cubic Bezier
curve.
- Figure 8. XML code for the green cubic Bezier
curve.
- Figure 9. XML code for the blue cubic Bezier
curve.
I recommend that you also study the other lessons in my extensive collection
of online Java tutorials. You will find a consolidated index at
www.DickBaldwin.com.
Paraphrasing the information in the SVG documentation, an SVG path represents
the outline of a shape. The shape can be filled, stroked, used as a
clipping path, or any combination of the three. It can also be used to
cause text to be positioned on curving lines, which will be the topic for a
future lesson.
A path is described using the concept of a current point. In an analogy
with drawing on paper, the current point can be thought of as the current
location of the pen. The position of the pen can be changed, and the outline of
a shape can be traced by dragging the pen in either straight lines or curves.
The shape can be either open or closed.
Paths represent the geometry of the outline of a shape, defined in terms of
the following commands:
- moveto (set a
new current point)
- lineto (draw a
straight line)
- curve (draw a
curve using a cubic or quadratic Bezier curve or an elliptical arc)
- closepath
(close the current shape by drawing a straight line to the last
moveto point)
A path is defined in SVG using the path
element.
The required d attribute
A path element can have a large number of optional attributes.
It appears from the documentation that all but two are common attributes that
can be applied to many different elements such as the attributes named
transform, style, etc.
It also appears from the documentation that there are at least two attributes
that are specific to a path element:
- d="path data"
- pathLength = "number"
A required data set
The d attribute is required while the pathLength attribute is
optional. The value for the d
attribute must be a data set that describes the path. In other words, the
data in the data set is the definition of the outline of the shape.
In summary, a path is defined by defining a path
element, which contains a d attribute, where the d-attribute value contains the
moveto, lineto,
curve, and
closepath commands and the
associated coordinate values necessary to define the outline of the shape.
Syntax of the path data set
The syntax of the path data set is designed to minimize download time and
associated bandwidth
requirements for downloading and drawing the path. The following rules generally describe the syntax of the
value of the d attribute:
- For download efficiency, all instructions (commands) are expressed
using a single character. For example, a
moveto command is
expressed as either M or m.
- Superfluous white space and separators such as commas can be eliminated.
For example, "M 100 100 L 200 200" contains unnecessary spaces and
could be expressed as "M100 100L200 200".
- The command letter can be eliminated on subsequent commands if the same
command is used multiple times in a row. For example, you can drop the
second "L" in "M 100 200 L 200 100 L -100 -200" and use "M 100 200
L 200 100 -100 -200" instead.
- Relative versions of all commands are available (uppercase means
absolute coordinates, lowercase means relative coordinates).
- For the relative versions of the commands, all coordinate values are
relative to the current point at the start of the command.
- Alternate forms of the lineto
command are
available to optimize the special cases of horizontal and vertical lines.
- Alternate forms of the
curve command are available to optimize the special cases where the
first control point on the current segment can be determined automatically from
the last control point on the previous segment.
- The path data syntax is a prefix notation (commands are followed by
parameters).
- The only allowable non-numeric characters for numeric parameter values
are the minus ("-") and period (".") characters. No other delimiter characters are allowed
within the parameter value. (For example, the following is
an invalid numeric value in path data: "13,000.56".)
The commands
If I counted correctly, there are twenty single-character commands that fall
in four general categories. The four categories and their single character
commands are given below:
- moveto: M or m
- closepath: Z or z
- lineto
- L or l (general lineto, [note the lowercase L])
- H or h (horizontal lineto)
- V or v (vertical lineto)
- curve:
- Cubic Bezier: C, c, S, and s (will
explain in detail later)
- Quadratic Bezier: Q, q, T, and t
(will explain in detail later)
- Elliptical arc: A and a
(will explain in detail later)
Recall that the uppercase version of each command indicates that the coordinate values
following the command are to be interpreted as absolute values and the lowercase version
of the command indicates that the coordinate values following the command are to be
interpreted as being
relative to "the current point at the start of the command."
The information in the above list is provided mainly to give you an overview.
I will discuss the different categories and their commands in much more detail later
in this lesson.
Figure 1 shows the graphic output that is produced by the program that I will
present and explain in this lesson.
Figure 1. The graphic output from the program.
Figure 1 illustrates a diagonal line, grid lines that give the appearance of
graph paper, a simple triangle composed of straight lines, three different cubic
Bezier curves, one quadratic Bezier curve, and six elliptical arcs. Each
of the shapes in Figure 1 was designed to illustrate one or more
features of the SVG path element. I will refer back to Figure 1 frequently throughout the remainder of this
lesson.
Throughout most of the earlier lessons in this series, I have been using a
Java/SVG
graphics library of my own design to make it easier to generate the detailed
SVG/XML
code required to render SVG graphics in an SVG-capable graphics engine. In several
previous lessons, I
have updated the library to add new functionality, and this lesson is no
exception.
I added the following new methods to my Java SVG graphics library for this lesson.
- makePath
- makeGridString
- makeText
I will present and explain the code
for these methods later. At this point, however, we are still
viewing the graphics process from a somewhat higher level and we don't need to
know the details of the code.
The moveto commands (M or m)
establish a new current point. The effect is as if the "pen" were lifted from
the paper and moved to a new location where it is then dropped back onto the
paper. A path data segment must begin with a moveto command. Subsequent
moveto commands represent the start of a new sub-path. (Note,
however, that I don't deal with multiple sub-paths in this lesson.)
|
|
Some special cases.
If a relative moveto (m) appears as the first element of the
path, it is treated as a pair of absolute coordinates. If a moveto is
followed by multiple pairs of coordinates, the subsequent pairs are treated as
implicit lineto commands. |
|
The moveto command must be followed by a pair of coordinate values that
specify the new current point. Depending on whether the command is an
uppercase M or a lowercase m, the coordinate values may be
either absolute or relative. The moveto command starts a new
sub-path at the location specified by the coordinate values.
The lineto command
The various lineto commands draw straight lines from the current point
to a new point that is specified by a pair of coordinate values following the
command.
The L or l lineto command
This command draws a line from the current point to the specified
coordinate which becomes the new current point. As usual, uppercase
L indicates that absolute coordinates will follow.
Lowercase l indicates that relative coordinates will follow.
A number of coordinate pairs may be specified to draw a polyline (not to
be confused with a polyline element). At the end
of the command, the new current point is set to the final set of coordinates
provided.
The H or
h lineto command
This is a special case of the lineto command that requires only a
single coordinate value following the command. The single coordinate value
is a new horizontal coordinate. This command draws a horizontal line from
the current point to the new horizontal coordinate at the same vertical
coordinate. (This command was used to draw the horizontal lines in the
blue background grid in Figure 1.)
The V or v lineto command
This is another special case of the lineto command that requires only
a single coordinate value following the command. The single coordinate
value is a new vertical coordinate. This command draws a vertical line
from the current point to the new vertical coordinate at the same horizontal
coordinate. (This command was used to draw the vertical lines in the
blue background grid in Figure 1.)
The closepath command
The closepath command (Z or z)
ends the current sub-path and causes an automatic straight line to be drawn from
the current point to the initial point of the current sub-path.
If a closepath is followed immediately by a moveto, then the
moveto identifies the start point of the next sub-path. If a closepath
is followed immediately by any other command, then the next sub-path starts at
the same initial point as the current sub-path.
The light blue grid pattern
The first thing that I will call your attention to in Figure 1 is the blue
grid of straight horizontal and vertical lines that causes the image to resemble a sheet of graph paper.
Why use the path element to draw straight lines?
You learned about the line and polyline elements in earlier
lessons in this series (see Resources).
The reality is that the use of the path element to draw straight lines is
conceptually more difficult than the use of the line element to draw straight lines. This may cause you to wonder
why you would ever use the path element to draw straight lines. The
reason is that in some cases, (such as the drawing of the background grid in
Figure 1), the use of the path element can significantly reduce the
size of the XML data download and the corresponding bandwidth requirements.
XML data required for a line element
Note the light blue diagonal line in Figure 1. This line was drawn
using a line element, and its only purpose for being in Figure 1 is to
illustrate the improved download efficiency of the path element relative
to the line element in
certain cases.
The XML code required to draw this line and to set its color to light blue
consisted of a total of 74 characters. This total would not
change significantly with changes in the length or the orientation of the line.
Downloading 74 characters to draw a line is not a problem if you are drawing only a few lines. However,
the light blue background grid in Figure 1 contains 45 horizontal lines and 45
vertical lines for a total of 90 lines. If each of those 90 lines had been
drawn and colored using an individual line element, approximately 6660
XML characters would have been required to draw all 90 lines.
Using a path element instead
As you will
see later, I developed a method named makeGridString that uses
special horizontal and
vertical lineto commands of the path element to reduce the
download size and attendant bandwidth requirements for drawings that contain a
large number of horizontal and vertical lines in a uniform grid pattern.
This method returns a string, which is used as the value for the attribute named
d for a path element that draws the lines described by the
contents of the string. Although the code to accomplish this is somewhat
more complicated than would be the case for drawing the grid using simple
line elements, the download size and bandwidth requirements are
significantly reduced with the use of the path element.
A significant reduction in XML data volume
|
|
polyline is more efficient than line.
I also wrote a test program and determined that the amount of XML code
required to draw the light blue grid using a polyline element was
about 1325 characters. Thus, the path element is also
more efficient than the polyline element, but not by nearly as large
a factor as when compared to the repeated use of the line element to
draw the grid. |
|
If I counted correctly, the XML code required to draw and color
all 90 of the light blue horizontal and vertical grid lines in Figure 1 using a
path element consists of
about 1150 characters. Thus, the use of the path
element to draw the light blue background grid reduced the amount of XML data by
almost a factor of 6 relative to the amount required to draw and color the grid using
individual
line elements.
The red and blue triangle
Next, I want to call your attention to the red triangle with the blue border
in the upper left corner of Figure 1. I used the moveto, lineto,
and closepath commands to draw this triangle. In fact, this program
uses one absolute moveto command, one absolute lineto command, and
one relative lineto command plus the closepath command to draw the triangle. Once the triangle
had been drawn, separate calls to the setAttribute method were made to
fill the triangle with red and to give it a blue border.
The triangle was drawn solely to illustrate the use of the path
element and the commands listed above. In reality, it would probably have
been easier to use simple line elements to draw this triangle than to
draw it using the path element.
The use of text in SVG is an extensive topic, one facet of which is to create
a curved path and then to render the text along that path instead of simply
rendering it along a straight line. Text will be the primary topic of a
future lesson.
However, I needed to put numeric labels on the graph shown in Figure 1 to make
it easier to read coordinate values off the graph. As you will see later,
I added a makeText method to my SVG graphics library to make this
relatively easy to
accomplish.
When you need to draw smooth curves to connect points, the path
element has a lot more to offer than just a reduction in the XML data volume,
although it has that to offer also. For this situation, the use of the
path element also makes it possible to do some things relatively easily that
could be very difficult to do otherwise.
|
|
Experimenting with Bezier curves.
If you would like to learn a little more about cubic Bezier curves and have
some fun in the process, take a look at the interactive Bezier Curve Demo in
Resources. (Also see Figure 2.) |
|
Cubic Bezier Curves
A Bezier curve is a smooth curve that is used to connect two points.
SVG supports both quadratic and cubic Bezier curves.
Initially, this
discussion will be centered on cubic Bezier curves. Then it will move
to quadratic Bezier curves.
Bezier curves according to Darrel Plant
While describing cubic Bezier curves, Darrel Plant tells us, "Almost any type of curve that
contains one or two changes in direction can be described by a Bézier equation." (See "What's a Bézier Curve?" in
Resources)
He
goes on to describe how cubic Bezier curves can also be used to describe loops and
other complex shapes.
Sample cubic Bezier curves
Figure 2 shows four different cubic Bezier curves that I created
interactively using the Bezier Curve Demo in
Resources.
Figure 2. Sample cubic Bezier curves.
In each of the individual images in Figure 2, the curved line is the
actual Bezier curve (or Bezier segment). The straight lines connect
the start point, two control points, and the end point that I will explain
in the next section.
|
|
A Bezier segment.
The SVG
documentation refers to the four points and the curve that they produce as a Bezier segment.
Thus, a Bezier curve may be made up of one or more Bezier segments. |
|
Drawing a Bezier segment
The locations of four points in coordinate space must be specified to draw a cubic Bezier segment.
There is a start point, two control points, and an end point. The segment is drawn from
the start point to the end point. The locations of the two control points
determine the shape of the curve as it winds its way from the start point to the
end point. Figure 2 shows some good examples of how the locations of
the two control points, relative to the locations of the start point and the end
point impact the shape of the actual Bezier curve or segment.
Special forms of the path element in SVG
With SVG, cubic Bezier segments are drawn using any one of several special forms of
the path element. There are four single-character commands that can be
used in the specification of the locations of the points: C, c, S, and s.
For example, Figure 3 shows the beginning of the XML path element that
produced the red Bezier curve shown immediately down and to the right of the red
and blue triangle in Figure 1.
Figure 3. Sample d attribute value for a cubic
Bezier curve.
<path
d="M100,100 C100,50 175,50 175,100 S250,150 250,100"
|
The C-command and the S-command are highlighted in boldface red
in Figure 3 to make them easy to for you to spot. (They would not be red in the
actual XML code.)
Either absolute or relative coordinates
|
|
Keeping the text uncluttered.
To keep the text from becoming too cluttered, the remainder of this discussion
on Cubic Bezier curves will use the uppercase version of the commands,
although in many cases the lowercase version could also be used. |
|
Once the start point has been established, the coordinates of the other three
points can be specified either in absolute coordinates or in coordinate values
that are relative to the location of the start point. If the uppercase
command is used, the coordinate values are interpreted to be absolute. If
the lowercase command is used, the coordinate values are interpreted to be
relative. Poly-Bezier curves
The specifications for multiple Bezier segments can be strung together following a Bezier
command to create a poly-Bezier curve. For example, each of the images
shown in Figure 2 is a single Bezier segment. On the other hand, the red
Bezier curve shown near the upper left in Figure 1 consists of two Bezier
segments concatenated end to end and is therefore a poly-Bezier curve.
For the case of poly-Bezier curves, each group of three
coordinate values following the original Bezier segment is interpreted
to represent the specification of a new Bezier segment. The start point for
the new segment is assumed to be the end point from the previous segment, and hence
serves as the first of the four points that are required to specify a cubic
Bezier segment.
Difference between C and S Bezier
commands
Of the two types of Bezier commands, (C and S), C is the more general
of the two. The C command can be used for a single
Bezier segment or for the construction
of a poly-Bezier curve. However, the S command applies only to the
construction of a poly-Bezier curve.
|
|
A reflected point.
In case you aren't certain what I mean when I speak of the reflection of a
point, see the links to the reflection articles in
Resources. |
|
When the S command is used to specify the four required points for the next
segment, only the second control point and the end point are actually specified. As is always the case for a poly-Bezier curve, the start point
for the next segment is assumed to be the end point from the
previous segment. However, when an S command is used, the first control point for the new segment is
assumed to be the reflection of the second control point from the previous
segment, leaving only two points that must actually be specified for the new
segment.
Quadratic Bezier curves
A quadratic Bezier segment is defined by a start point, an end point, and
only one
control point. As with the cubic Bezier segment, there are four commands that are used to specify the locations of the three required points:
Q, q, T and t.
The uppercase commands imply that the coordinate values are absolute while the
lowercase commands imply that the coordinate values are relative to the location
of the start point.
The Q and q commands for the quadratic segment have essentially
the same meaning as the C and c commands for the cubic segment.
The T and t commands for a quadratic segment have essentially the
same meaning as the S and s commands for the cubic segment.
The Bezier curves in Figure 1
Figure 1 contains three cubic Bezier curves colored red, green, and blue, and one quadratic Bezier curve
colored red.
I will have more to say about each of these curves in conjunction with the
explanation of the Java code that produced them.
Seven parameters are required
An elliptical arc command is perhaps the most complex of all of the curve
commands. Each elliptical arc command requires seven parameters in the
following order:
- rx specifies the horizontal radius of the ellipse
- ry specifies the vertical radius of the ellipse
- x-axis-rotation specifies the rotation of the ellipse relative to
the current coordinate system
- large-arc-flag (will discuss in detail later)
- sweep-flag (will discuss in detail later)
- x specifies the horizontal location of the end point of the arc
- y specifies the vertical location of the end point of the arc
Behavior of the elliptical arc command
The command draws an elliptical arc beginning at the current point and ending
at the location specified by x and y.
The coordinates of the center of the ellipse are calculated automatically to
satisfy the constraints imposed by the other parameters. The
large-arc-flag and sweep-flag parameters contribute to
the automatic calculations and help determine how the arc is drawn.
The large-arc-flag and sweep-flag
parameters
Each of the parameters named large-arc-flag and sweep-flag can
have a value of 0 or 1. This results in four possible combinations of
these two parameters. Thus, there are actually four different arcs (two
different ellipses, each with two different arc sweeps), only one of which
can satisfy the
constraints imposed by a specific combination of these two parameters.
The rules for drawing elliptical arcs
The combination of
large-arc-flag and sweep-flag indicates which one of
the four arcs will be drawn according to the following rules:
- Of the four candidate arcs, two represent an arc sweep of greater than
or equal to 180 degrees. This is a large arc. The other
two candidates
represent an arc sweep of less than or equal to 180 degrees. This is a
small arc.
If the value of large-arc-flag is 1, one of the two
larger arc sweeps will be chosen.
If the value of large-arc-flag is 0, one of the smaller arc
sweeps will be chosen,
- The arc is drawn by evaluating the following equations where cx
and cy are the coordinates of the center of the ellipse:
x = cx + rx*cos(theta)
y =cy + ry*sin(theta)
If the value of sweep-flag is 1, then the equations are
evaluated such that theta starts at an angle corresponding to the current
point and increases positively until the arc reaches the end point.
If the value of sweep-flag is 0, the equations are
evaluated such that theta starts at an angle value corresponding to the
current point and decreases until the arc reaches the end point.
Elliptical arcs in the graphical output
Six elliptical arcs are shown in Figure 1. The yellow arc with the red
border and the red arc with the yellow border illustrate the effect of the
x-axis-rotation parameter on the appearance of the arc. The yellow arc
with the red border was drawn with an x-axis-rotation parameter value of
0. The red arc with the yellow border was drawn with an x-axis-rotation
parameter value of 45 degrees.
In both cases, the start point was at the bottom of the straight-line segment
on the left and the end point was at the top of the straight-line segment.
Also in both cases, the value of
large-arc-flag was 1 and the value of sweep-flag
was 0. Thus, as explained above, one of the two
larger arc sweeps was chosen in each case. Also as explained above, the equations
were evaluated such that theta started at an angle value corresponding to the
current point and decreased until the arc reached the end point.
Combinations of large-arc-flag and
sweep-flag
Each of the other four elliptical arcs at the bottom of Figure 1 represents
one of the four possible combinations of large-arc-flag and
sweep-flag with an x-axis-rotation parameter value
of 0. Note that in each case, the horizontal and vertical radii were
the same, causing the elliptical arc to actually be a circular arc. Also
note that in each case, the start point of the elliptical arc was at the bottom
of the straight-line segment.
Figure 4 shows the different combinations of these two parameters
for each elliptical arc going from left to right across Figure 1.
Hopefully a comparison of these parameter values with the images in Figure 1
will help you to understand the impact of each of the two parameters on the
appearance of the elliptical arc.
Figure 4. Combinations of large-arc-flag and
sweep-flag.
Case 1: Fill color = red, border = blue
large-arc-flag = 1
sweep-flag = 0
Case 2: Fill color = green, border = red
large-arc-flag = 1
sweep-flag = 1
Case 3: Fill color = blue, border = red
large-arc-flag = 0
sweep-flag = 0
Case 4: Fill color = yellow, border = blue
large-arc-flag = 0
sweep-flag = 1
|
The large-arc flag
The behavior of the
large-arc-flag
is pretty straightforward and easy to understand. Basically the value of the large-arc-flag
determines whether the large portion or the small portion of the ellipse will be
displayed. If the
large-arc-flag has a value of 1, the large portion of the ellipse will be
displayed. If the
large-arc-flag has a value of 0, the small portion will be displayed.
The sweep-flag
The behavior of the
sweep-flag is not so straightforward, at least not for me anyway.
The value of the sweep-flag
determines which side of the straight-line segment the portion selected by the
large-arc-flag will be
displayed on. However, the difference between right and left in this case
depends on the locations of the start point and the end point.
Although I haven't worked out the math, I feel reasonably confident in saying
that if you stand at the start point and look toward the end point, the arc will
be displayed on your right if the
sweep-flag
has a value of 0, and will be displayed on your left if the
sweep-flag has a value of 1.
I will present and explain a program named Svg12 in this lesson.
The primary purpose of this program is to teach you how to use an SVG path
element to draw straight lines, Bezier curves, and elliptical arcs. The program produces a single SVG file as its output. The
graphic output shown in Figure 1 was produced by rendering the SVG output file using
Firefox 1.5.
As is my custom, I will present and explain the program in fragments.
You can view a listing of the entire program in Listing 17 near the end of the
lesson.
Discussion
and sample code
Overall, the program creates a DOM tree
that describes the graphic image shown in Figure 1 in SVG format and writes it out into an
SVG
file named Svg12.svg. The output file produced by this program can be rendered by
loading it into Firefox 1.5.
The path element
The main purpose of this program is to demonstrate the use of a
Java method of my own design named makePath to create the SVG/XML output
code necessary to produce the graphic elements shown in Figure 1. A
secondary purpose is to demonstrate the use of a second Java method of my own
design named makeGridString.
I updated my SVG graphics library during the writing of this program to add several new
methods, including makePath and makeGridString, and to update some of the default values for existing methods
as well.
A diagonal blue line
The program uses a line element to draw a diagonal line from the top
left corner of Figure 1 to the lower right corner. The purpose of this
line was to provide information about the line element that could be used
to calculate the improvement in download
efficiency provided by the path element relative to the line
element for certain cases involving straight lines.
A background grid
|
|
What color is graph paper?
In retrospect, thinking back to the days when I actually used graph
paper, I probably should have made the background grid green. Then it
would look even more like the graph paper that I remember from those days.
|
|
After taking care of all the preliminary stuff that I have explained in
earlier lessons, the program uses the new method named makeGridString
in
conjunction with the new method named
makePath
to draw a light blue background grid that
resembles graph paper. The
makeGridString
method uses the
moveto
command and
special versions of the horizontal and vertical
lineto
command to reduce the
amount of SVG/XML data needed to draw the grid.As you can see in Figure 1, there are light blue horizontal
and vertical lines every 10th pixel. There are slightly darker blue lines every
50th pixel. There are even darker blue lines every 100th pixel.
The text labels
The program uses a new Java method of my own
design named makeText to place black text labels on the blue lines that mark every 50th pixel.
A red triangle with a blue border
Then the program uses the moveto,
lineto, and closepath commands to draw
a triangle. The setAttribute method is used to fill the triangle
with solid red color and to give it a blue border.
Three cubic Bezier curves
The program draws three cubic Bezier
curves, one red, one green, and one blue, illustrating the effect that the locations of the control points
have on the
shape of the curve.
One quadratic Bezier curve
Then the program overlays a
red quadratic Bezier curve on the blue cubic Bezier curve, illustrating the
difference in the degree to which the cubic and quadratic Bezier curves fit the
same envelope, where the envelope is defined by the start point, the control point(s), and the end point.
Elliptical arc rotation
The program draws two elliptical arc
curves to illustrate the effect of the x-axis-rotation parameter on the appearance
of the elliptical arcs. The yellow arc with the red border has a rotation
value of zero, while the red arc with the yellow border has a rotation value of
45 degrees. Otherwise, the two elliptical arcs were drawn with the same
parameter values.
Combinations of large-arc-flag and
sweep-flag parameters
Finally, the program draws four more elliptical arc curves,
illustrating the difference in shape that results from all four combinations of
the large-arc-flag and
sweep-flag parameters.
Program testing
The program was tested using J2SE 5.0, Firefox v1.5.0.8, and WinXP.
The class named Svg12 begins in Listing 1.
Listing 1. The beginning of the class named Svg12.
public class Svg12{
public static void main(String[] args){
int width = 450;
int height = 450;
//Begin by creating a DOM tree that represents the XML
// code that will render to produce the image of
// interest.
//Get the Document object.
Document document = SvgGraphics.getDocument();
//Create the root node named svg and append it to the
// document. Specify the parent as null for the
// special case where the parent is the document.
Element svg = SvgGraphics.makeNode(
document,
null,//parent
"svg",//node type
new String[]{"xmlns","http://www.w3.org/2000/svg",
"version","1.1",
"width",""+ (width + 2),
"height","" + (height + 2),
"position","absolute",
"top","0",
"left","0",
});//end makeNode method
//Create a node named g, which will be the parent for
// several graphic elements. Pass null for the
// reference to the array object for the special case
// where the node has no attributes.
Element g = SvgGraphics.makeNode(document,
svg,//parent
"g",
null);
|
I have explained the material in Listing 1 in previous lessons, so I won't
repeat that explanation here.
Listing 2 calls the makeLine method to draw a diagonal line from the
upper left corner to the bottom right corner in Figure 1, and then calls the
setAttribute method to color it blue.
Listing 2. Draw a diagonal line.
Element diagLine = SvgGraphics.makeLine(
document,g,0,0,450,450);
diagLine.setAttribute("stroke","#8888ff");
|
I explained both of these methods in earlier lessons, and won't repeat that
explanation here.
Listing 3 calls the makeGridString method followed by the makePath
method and the setAttribute method to draw the light blue grid lines on a
ten-pixel spacing in Figure 1. This is the first of three sets of grid
lines, followed by a set on 50-pixel spacing and a set on 100-pixel spacing.
Listing 3. Draw the light blue grid lines.
//First draw light blue grid lines every 10 pixels.
String gridData = SvgGraphics.makeGridString(
width,height,10);
//Create the path element.
Element temp;
temp = SvgGraphics.makePath(document,g,gridData);
//Set the color to light blue.
temp.setAttribute("stroke","#ccccff");
|
Both the makeGridString method and the makePath method are new
to this lesson, so I will put the discussion of the main method on hold
while I explain these two methods. I will explain them in reverse order
because, in effect, the makeGridString method is a helper method for the
makePath method. Therefore, I will explain the makePath
method first.
The makePath method
The makePath method is shown in its entirety in Listing 4.
Listing 4. The makePath method.
static Element makePath(Document document,
Element parent,
String d){
Element path =
(Element)document.createElement("path");
parent.appendChild(path);
path.setAttribute("d",d);
path.setAttribute("stroke","black");
path.setAttribute("stroke-width","1");
path.setAttribute("fill","none");
return path;
}//end makePath
|
Let me begin by reviewing what is going on here. At this point in the
program, I am constructing a DOM tree that represents the graphic image shown in
Figure 1. At this point, the objective is to create nodes in the DOM tree
that will later be transformed into elements in the XML output code produced by
the program.
With the exception of the diagonal line and some polylines, all of the shapes in Figure 1 will
be created using an SVG/XML path element. This includes the
background grid lines. Therefore, at this point, I need to create a node
of type path and append it to the Dom tree.
Old stuff
There is nothing new about the first two parameters to the makePath
method: document and parent. Almost all of the
methods in my SvgGraphics library require these parameters and I have explained
their use in earlier lessons. There is also nothing new about the first
statement or the last four statements in the method. I have also explained
these statements in earlier lessons. That leaves only one interesting
statement, and it is highlighted in boldface in Listing 4.
New stuff
In the earlier section titled The
required d attribute, I explained that an SVG path element must have
an attribute named d. I also explained that the value of the d
attribute must be a data set that describes the path. In other words, the
data in the data set is the definition of the outline of the shape represented
by the path.
In the section titled Syntax of the
path data set I explained the rules for constructing the string attribute
value for the d attribute. Briefly, that string must consist of
uppercase and lowercase alphabetic commands and numeric coordinate values.
Establish the value of the attribute named d
After constructing the path node and appending it to the DOM tree, the
makePath method in Listing 4 calls the setAttribute method on the
path node, passing the third parameter to the makePath method as
the only parameter to the setAttribute method. Therefore, the
string contents of the parameter named d will become the attribute value
for the path element when the DOM tree is transformed to XML. The |