Summary：The parametric curve representation is useful for geometric calculation such as
calculating intersection points of two curves etc. We extends the classes
of the Rectangle2D, RoundRectangle2D, Ellipse2D and so on in java.awt.geom
to be able to handle a parametric curve.

Relevant major classes of Java SE: java.awt.*, java.geom.*

Classes on this page: Segment2D,
geomExtension, Curve2D,
Rectangle2DE, RoundRectangle2DE,
Ellipse2DE, Line2DE,
Polyline2DE, CubicCurve2DE,
GeneralCurve2DE, FergusonCurve2D 
1. Overview of the parametric curve
1.1 The definition
A two dimensional parametric curve is defined by a parameter t and two
functions (Cx(t), Cy(t)) which give the (x,y) coordinates for parameter
t. We denote the parametric curve as follow.
(1)
The Cx(t) and Cy(t) are usually expressed by a piecewise function.
Each piece is a polynominal function, circular functions and so on.
For example, the bondary curve of the java.awt.geom. RoundRectangle2D consists of eight pieces  four
straight lines and four arcs of the 90° central angle 
and those pieces are arranged as line>arc>line>arc>⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ .
We defines the domain (interval) of the curve parameter t for each
piece as 0≤t≤1 for the first piece, 1≤t≤2 for the second piece and so on.
Hereafter we call each piece as a curve segment or a segment and the junction point of two pieces as a segment junction point.
Let's denote the number of the curve segments of a parametric curve as
nseg, then the curve segments numbered as 0,1,2⋅ ⋅ ⋅ ,nseg1, and
the segment junction points are numbered as 0,1,2⋅ ⋅ ⋅ ,nseg.
1.2 The expressions of parametric curve segment
(1) Elliptic arc (circular arc)
The elliptic arc corresponds to the java.awt.geom.Arc2D and its parametric
curve ie expressed as follow
Cx(t)= a*cos((θextent*t+θstart)*π/180)+x0 (2)
Cy(t)=  b*sin((θextent*t+θstart)*π/180)+y0
The plus direction of the yaxis on the screen is downward, so a minus sign is needed
for the expression of the Cy(t).
Here, (a) the angles are represented in degrees, (b) the plus rotation of the angle is anticlockwise.
And the notations in the (2) are as follow.
⋅ (x0,y0): The center of the arc.
⋅ a, b: the The transverse diameter and conjugate diameter.
⋅ θextent: The angular extent of the arc in degrees.
⋅ θstart: The starting angle of the arc in degrees.
⋅ π: The circle ratio.
(2) CubicCurve(Bezier curve segment)
P(t)=(1t)^{3} Q_{0 }+ 3(1t)^{2}t
Q_{1 }+ 3(1t)t^{2} Q_{2 }+ t^{3}Q_{3} (A bold character represents a vector)
(3)
The Bezier curve segment consists of four points. The Q_{0}, Q_{3} are
the endpoints of the segment, and Q_{1}, Q_{2} are
the control points which the segment doesn't generally pass through.
Table 1 Blending functions

X_{0}(t)

X_{1}(t)

X_{2}(t)

X_{3}(t)

X_{i}(t)

(1t)^{3}

3(1t)^{2}t

3(1t)t^{2}

t^{3}

First derivatives: X_{i}^{'}(t)

3(1t)^{2}

3(1t)(13t)

3(23t)t

3t^{2}

Second derivatives: X_{i}^{''}(t)

6(1t)

6(23t)

6(13t)

6t

Table 2 The function and the derivatives at t=0, 1

t=0

t=1

P(t)

Q_{0}

Q_{3}

First derivatives: P^{'}(t)

3Q_{0}+3Q_{1} 
3Q_{2}+3Q_{3}

Second derivatives: P^{''}(t)

6Q_{0}12Q_{1}+6Q_{2}
=6(Q_{2}Q_{1}) 6(Q_{1}Q_{0})

6Q_{1}12Q_{2}+6Q_{3}
=6(Q_{3}Q_{2}) 6(Q_{2}Q_{1})

(3) Ferguson curve segment
The Bezier curve can be rewritten as follows:
P(t)= X_{0}(t)Q_{0 }+ X_{1}(t)Q_{1 }+ X_{2}(t)Q_{2 }+ X_{3}(t)Q_{3}
= (X_{0}(t)+X_{1}(t))Q_{0 }+ X_{1}(t)(Q_{1 } Q_{0 })  X_{2}(t)(Q_{3 } Q_{2 }) + (X_{2}(t)+X_{3}(t))Q_{3}
= (X_{0}(t)+X_{1}(t))P(0) + (X_{2}(t)+X_{3}(t)) P(1) + X_{1}(t)/3 P^{'}(0)  X_{2}(t)/3 P^{'}(1)
= f_{0}(t) P_{0 }+ f_{1}(t)P_{1 }+ g_{0}(t) T_{0 } g_{1}(t)T_{1}
(4)
The last formula is the expression of the Ferguson curve segment.
Here, P_{0}= P(0),
P_{1}= P(1), T_{0}= P^{'}(0),
T_{1}= P^{'}(1)
=>
Figure 1.1 (a)
and the functions of f_{0}(t), f_{1}(t),
g_{0}(t) and g_{1}(t) are expressed as Table 3.
Table 3 Ferguson blending functions

f_{0}(t)
= X_{0}(t)+ X_{1}(t))

f_{1}(t)
= X_{2}(t)+X_{3}(t)

g_{0}(t)
= X_{1}(t)/3

g_{1}(t)
= X_{2}(t)/3

f_{i}(t), g_{i}(t)

(1t)^{2}(1+2t)

(32t)t^{2}

(1t)^{2}t

(1t)t^{2}

First derivatives: f_{i}^{'}(t), g_{i}^{'}(t)

6(1t)t

6(1t)t

(1t)(13t)

(23t)t

Second derivatives: f_{i}^{''}(t), g_{i}^{''}(t)

6+12t

612t

4+6t

26t

The relation of the functions:
f_{0}(t)= f_{1}(1t), f_{0}(1t)= f_{1}(t),
g_{0}(t)= g_{1}(1t), g_{0}(1t)= g_{1}(t)
The expression of (4) may be convenient for handling the tangent vectors
of the curve segment because the tangent vectors are expressed explicitly.
The definition of Tin, Tout
A spline curve can be represented by multiple Ferguson segments. In this
case, two tangent vectors are defined at the ith segment junction point  the first
tangent vector is used for interpolate the (i1)the segment and the second
is for the ith segment. Those tangent vectors are denoted by P^{'}(1)
and P^{'}(0) in the (4) and hereafter those vectors are denoted by Tin[i] and Tout[i]
respectively.
In the case of a smooth spline, the directions of Tin[i] and Tout[i] are
the same, however the lengths of Tin[i] and Tout[i] are not equal in general.
Figure 1.1 Curve segment and Tin, Tout
Annotation: The real (mathematical) direction of the Tin is the inverted direction
that the Figure shows.
2. Class Segment2D
return=>page top
public class Segment2D
The Segment2D class represents a parametric curve segment of Line2D,
Arc2D and CubicCurve2D in the java.awt.geom package. The QuadCurve2D
in the java.awt.geom is not used for the parametric curve segment, because
it doesn't seem useful.
The major function of the Segment2D class is to calculate the position,
tangent vector and second derivative vector of the parametric curve segment
for a given parameter t (0≤t≤1) by
the expression of the parametric curve segment.
Field 
Description 
type

int type
This field represents the type of the parametric curve segment.
One of the LINE, ARC or CUBIC is set to this filed.

shape 
private Shape shape
One of the Line2D, Arc2D or CubicCurve2D object in the java.awt.geom
is set to this field according to the type.

affineTransform

private AffineTransform affineTransform
Stores the AffineTransform for the Arc2D object.
If the type equals Line or CUBIC, this field is not used to represent a transformed
object, because the transformed object can be created from the original
Line2D or CubicCurve2D object by transforming is endpoints and control points.

MOVETO

public static final int MOVETO=0
The constants to be set to the type field.
Moves a point to the start point of the next subpath.

LINE

public static final int LINE=1
The constants to be set to the type field.
The Line2D object is set to the shape field.

ARC

public static final int ARC=2
The constants to be set to the type field.
The Arc2D object is set to the shape field.

CUBIC

public static final int CUBIC=3
The constants to be set to the type field.
The CubicCurve2D object is set to the shape field.

QUAD

public static final int QUAD=4
The constants to be set to the type field.
The QuadCurve2D object is set to the shape field.
Not used currently.

Method 
Description 
Constructor

public Segment2D(int type, Shape shape)
Sets the parameters to the corresponding field.
Null is set to the affineTransform field.

Constructor

public Segment2D(int type, Shape shape, AffineTransform affineTransform)
Sets the parameters to the corresponding field.

getType

public int getType2()
Returns the type field.

isAffineTransform 
public boolean isAffineTransform()
Return true if the affineTransform isn't null.

getShape

public Shape getShape()
Returns the shape field.
If thetype equals ARC and the
affineTransform isn't null,
then return the java.awt.geom.GeneralPath object which is created by using the
shape and the affineTransform.
=>
Returning the transformed Arc2D

getP

public Point2D getP(double t)
Parameter:
t  The parameter of the curve segment.. 0≤t≤1.
Returns:
The position (x,y) of the curve segment at the parameter t.

getTangent

public Vector2D getTangent(double t)
Parameter:
t  The parameter of the curve segment. 0≤t≤1.
Returns:
The derivative (tangent vector) of the curve segment at the parameter t.

getTangentDerivative

public Vector2D getTangentDerivative(double t)
Parameter:
t  The parameter of the curve segment. 0≤t≤1.
Returns:
The second derivative (vector) of the curve segment t at the parameter t.

getEndPoints 
public Point2D[] getEndPoints()
Returns the endPoints of this object. 
getCharacteristicPoints 
public CurvePT[] getCharacteristicPoints()
Returns the characteristic points of this object. Characteristic points
are endpoints and middle points of the curve segments of this object, and
north, south, east and west points of an ellipse or a circle. 
getSegmentLength

public double getSegmentLength(double t1, double t2)
Returns the curve length of the curve segment interval (t1≤t≤t2). 0≤t1, t2≤1.

getBoundingBox

public Rectangle2D getBoundingBox()
Returns the bounding box enclosing the curve segment.

getBoundingBox

public Rectangle2D getBoundingBox(double t1, double t2)
Returns the bounding box enclosing the curve segment interval (t1≤t≤t2).
0≤t1, t2≤1

resizeSegment

public Segment2D resizeSegment(Rectangle2D oldBox, Rectangle2D newBox)
Parameters:
oldBox  The previous dragged rectangle.
newBox  The current dragged rectangle.
Returns:
The resized Segment2D object.
Processing:
⋅ If the affineTransform equals null,
then performs the following.
Creates the resized Line2D, Arc2D or CubicCurve2D objects and creates
a new Segment2D object using the type and the resized object.
⋅ If the type equals ARC and the
affineTransform doesn't equals null,
then performs the following.
Creates a transforming matrix by the
getResizeMatrix method of the
Matrix2D.
And calculates the multiplied matrix by the affineTransform
and the transforming matrix, then returns a new Segment2D object
which is created by using the type,
the shape and the multiplied matrix.

trimSegment

public Segment2D trimSegment(double t1, double t2)
Parameters:
t1  The start parameter of the trimmed segment.
t2  The end parameter of the trimmed segment.
0≤t1, t2≤1
Returns:
The trimmed Segment2D object.
Processing:
Creates the trimmed Shape object of Line2D, Arc2D or CubicCurve2D.
Then creates a new Segment2D object using the
type, the trimmed Shape and the
affineTransform, and returns the new Segment2D.

getFergusonCurve

public FergusonCurve2D getFergusonCurve()
Returns:
The FergusonCurve2D object converted from this Segment2D object.
Processing:
⋅ If the type equals LINE or CUBIC, then performs the following.
In this case, the Segment2D object can be converted to a single Ferguson
segment within roundoff error. So, returns the FergusonCurve2D of single segment.
⋅ If the type equals ARC, then performs the following.
The Segment2D can be approximated with multiple Ferguson segments by using
the getOptimizedTangents method of the FergusonCurve2D. The number of the Ferguson segments is determined so that the approximation error
is lower than 1e8 for a unit circle.
As the result, the error range can be lower than 1e4 for any shape
on the canvas. In this case, returns the FergusonCurve2D of multiple segments.

transformSegment

public Segment2D transformSegment(Matrix2D M)
Parameters:
M  The transforming matrix.
Returns:
The transformed Segment2D object.
Processing:
⋅ If the type equals Line2D or CubicCurve2D, then performs the following.
Creates a new Line2D or CubicCurve2D object by transforming the endpoints
and control points of the shape
and creates a new Segment2D object using the type
and the new Line2D or CubicCurve2D object.
⋅ If the type equals ARC, then performs the following.
Calculates the multiplied matrix of the affineTransform
and the transforming matrix M and created a new Segment2D object by using the
type, the shape and the multiplied matrix.
Then returns the new Segment2D object.

reverseSegment

public Segment2D reverseSegment()
Returns:
The Segment2D object which is reversed in curve direction.
Processing:
Creates a new Line2D, Arc2D or CubicCurve2D object whose direction is reversed
and creates a new Segment2D object using the type
and the reversed object, then returns the new Segment2D object.

moveSegmentEndPT 
public Segment2D moveSegmentEndPT(int index, Point2D newPT)
Parameters:
index  if the index equals 0, then move the start point of the curve segment,
otherwise moves the end point of the curve segment.
newPT  The new endpoint.
Returns:
The Segment2D object whose specified endpoint was moved to the newPT.
Processing:
⋅ The case of the type equals LINE
Replaces the specified endpoint by the newPT.
⋅ The case of the type equals ARC
Creates the transforming matrix by the
getRotationMatrix method of the
Matrix2D
and transforms this Segment2D object by the
transformSegment method.
⋅ The case of the type equals CUBIC
Creates a new segment2D object by using the
movePoint method of the
FergusonCurve2D.

moveSegmentTangent 
public void moveSegmentTangent(int index, Vector2D newTangent)
Parameters:
index  if the index equals 0, then changes the tangent line at the start point,
otherwise changes the tangent line at the end point of the curve segment.
newtangent  The new tangent vector.
Returns:
The Segment2D object whose direction of the tangent line at the specified
endpoint was changed to the the direction of the newTangent.
Processing:
This method is used only for the Segment2D object whose type equals CUBIC.
Creates a new segment2D object by using the moveTangent method
of the FergusonCurve2D.

clone

public Object clone()
returns the clone of this object.

toString

public String toString()
Returns the string representing this object.

getSerializableSegment2D

public SerializableSegment2D getSerializableSegment2D()
Returns the SerializableSegment2D object
which is used for writing this object to the file.

:
Returning the transformed Arc2D
Shape shape=this.shape;
if(this.type==ARC&&this.affineTransform!=null){
GeneralPath generalpath=new GeneralPath();
generalpath.append(shape, false);
generalpath.transform(this.affineTransform);
shape=generalpath;
}
return shape;
3. The extension of java.awt.geom (geomExtension)
return=>page top
We extends the classes of the Rectangle2D, RoundRectangle2D, Ellipse2D etc. in java.awt.geom
package to be able to handle a parametric curve. The names
of the extended classes are denoted by adding "E" at the end
of the original class names  Rectangle2DE, RoundRectangle2DE, Ellipse2DE etc.
The each extended class has the array of parametric curve segments (Segment2D objects) and the java.awt.Shape object.
The array of the parametric curve segments is used for calculating the
position (x,y), the tangent vector and the second derivative of the parametric
curve. The Shape object is used for drawing the shape of the parametric
curve by the methods of java.awt.Graphics and java.awt.Graphics2D. And
the Shape object is also used for testing whether a specified point
is inside the boundary of the Shape or not, by the contains method
of the Shape.
Creating the java.awt.Shape object of a parametric curve
The java.awt.geom.GeneralPath is employed to create the Shape object of
the parametric curve as follows.
Example：The constructor of the RoundRectangle2DE
A round rectangle consists of eight pieces of shapes  four
straight lines and four arcs of the 90° central angle 
and those pieces are arranged as line>arc>line>arc>⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅ ⋅ as mentioned in 1.1.
public RoundRectangle2DE(double x, double y, double width, double height,
double arcw, double arch){
this.x=x; this.y=y; this.width=width; this.height=height;
this.arcw=arcw; this.arch=arch;
this.generalPath=new GeneralPath();
this.segments=new Segment2D[8];
Line2D line0=new Line2D.Double(x, y+0.5*arch, x, y+height0.5*arch);
Line2D line1=new Line2D.Double(x+0.5*arcw, y+height, x+width0.5*arcw, y+height);
Line2D line2=new Line2D.Double(x+width, y+height0.5*arch, x+width, y+0.5*arch);
Line2D line3=new Line2D.Double(x+width0.5*arcw, y, x+0.5*arcw, y);
Arc2D arc0=new Arc2D.Double(x, y+heightarch, arcw, arch, 180, 90, Arc2D.OPEN);
Arc2D arc1=new Arc2D.Double(x+widtharcw, y+heightarch, arcw, arch, 270,
90, Arc2D.OPEN);
Arc2D arc2=new Arc2D.Double(x+widtharcw, y, arcw, arch, 0, 90, Arc2D.OPEN);
Arc2D arc3=new Arc2D.Double(x, y, arcw, arch, 90, 90, Arc2D.OPEN);
segments[0]=new Segment2D(Segment2D.LINE, line0);
segments[1]=new Segment2D(Segment2D.ARC, arc0);
segments[2]=new Segment2D(Segment2D.LINE, line1);
segments[3]=new Segment2D(Segment2D.ARC, arc1);
segments[4]=new Segment2D(Segment2D.LINE, line2);
segments[5]=new Segment2D(Segment2D.ARC, arc2);
segments[6]=new Segment2D(Segment2D.LINE, line3);
segments[7]=new Segment2D(Segment2D.ARC, arc3);
for(int i=0;i<segments.length;i++){
Shape shape=segments[i].getShape();
generalPath.append(shape,true);
}
generalPath.closePath();
}
4. abstract class Curve2D
return=>page top
public abstract class Curve2D
This class provides basic and common methods of the parametric curve. The
other classes are the extended classes of this abstract class.
Field 
Description 
segments

Segment2D[] segments
The Segment2D objects which compose this parametric curve.

generalPath

GeneralPath generalPath
The GeneralPath object which is referred as java.awt.Shape in getShape method..
This object is created by appending the shape  Line2D, Arc2D or CubicCurve2D  of
Segment2D objects in the Curve2D constructor.
=>
Creating and extracting java.awt.Shape

closed

boolean closed
True if this parametric curve is closed.

Constants which represent Curve2D extensions

public static final int RECTANGLE=1, ROUND_RECTANGLE=2, ELLIPSE=3, LINE=4,
POLYLINE=5, CUBIC_CURVE=6, GENERAL_CURVE=7
The constants representing the type of the extended classes of this class.

eps

public final static double eps=1e5
The small number.

largeNumber 
public final static double largeNumber=1e+5
The large number. 
ClosedTolerance 
public final static double ClosedTolerance=3d
The number used for testing whether the parametric curve is closed
or not. 
Method 
Description 
Constructor

public Curve2D(Segment2D[] segments)
Create a new Curve2D object with the Segment2D objects.
this.segments=segments;
this.generalPath=new GeneralPath();
Point2D startP=segments[0].getP(0);
Point2D endP=segments[segments.length1].getP(1);
double dist=Vector2D.dist(new Vector2D(startP), new Vector2D(endP));
this.closed=false;
if(dist<Curve2D.eps) closed=true;
for(int i=0;i<segments.length;i++) {
Shape shape=segments[i].getShape();
this.generalPath.append(shape,true);
}
if(this.closed) this.generalPath.closePath();

setData

public void setData(Segment2D[] segments)
Performs the same processing as the constructor.

getType2DE
(abstract)

public abstract int getType2DE()
Return the type of this parametric curve.
The types are RECTANGLE,
ROUND_RECTANGLE, ELLIPSE and so on.

getShape

public Shape getShape()
Return the generalPath field.
=>
Creating and extracting java.awt.Shape

isClosed 
public boolean isClosed()
Rturns the closed field. 
getNumOfSegments

public int getNumOfSegments()
Returns the number of the curve segments (segments field).

getSegment2Ds

public Segment2D[] getSegment2Ds()
Return the segments.

getSegment2D

public Segment2D getSegment2D(int Index)
Return the curve segment specified by the index.

getP

public Point2D getP(double t)
Parameter:
t  The parameter of the curve segment.
0≤t≤nseg, nseg: the returned value of the getNumOfSegments.
Returns:
The position (x,y) of the parametric curve at the t.

getTangent

public Vector2D getTangent(double t)
Parameter:
t  The parameter of the curve segment.
0≤t≤nseg, nseg: the returned value of the getNumOfSegments.
Returns:
The derivative (tangent vector) of the parametric curve at the t.

getTangentDerivative 
public Vector2D getTangentDerivative(double t)
Parameter:
t  The parameter of the curve segment.
0≤t≤nseg, nseg: the returned value of the getNumOfSegments.
Returns:
The second derivative vector of the parametric curve at the t.

getEndPoints 
public Point2D[] getEndPoints()
Returns the endpoints.

getCharacteristicPoints 
public CurvePT[] getCharacteristicPoints()
Returns the characteristic points. The characteristic points are endpoints
of a line/curve segment, and north, south, east and west points of an ellipse/circle.
=>
ConnectionLS Figure 1

getCurveLength

public double getCurveLength(double t1, double t2)
Parameters:
t1  The start parameter of the interval.
t2  The end parameter of the interval.
0≤t1, t2≤nseg, nseg: the returned value of the getNumOfSegments.
Returns:
Returns the curve length of the interval (t1≤t≤t2).

getBoundingBox

public Rectangle2D getBoundingBox()
Returns the bounding box enclosing the parametric curve.

getBoundingBox

public Rectangle2D getBoundingBox(double t1, double t2)
Parameters:
t1  The start parameter of the interval.
t2  The end parameter of the interval.
0≤t1, t2≤nseg, nseg: the returned value of the
getNumOfSegments.
Returns:
Returns the bounding box enclosing the curve interval (t1≤t≤t2) of the parametric curve.

getSerializableCurve2D

public SerializableCurve2D getSerializableCurve2D()
Returns:
The SerializableCurve2D object
which is used for writing this object to the file.

setSerializableCurve2D 
public void setSerializableCurve2D(SerializableCurve2D sdata)
Parameters:
sdata  The SerializableCurve2D object
which is used for writing this object to the file.
Processing:
Sets the contents of the sdata to this object.

convertToGeneral
Curve2DE

public GeneralCurve2DE convertToGeneralCurve2DE()
Converts this object to the GeneralCurve2DE object.
This method is used for rotating Rectangle2DE, RoundRectangle2D etc.

reverse 
public void reverse()
Reverses the direction of parametric curve by using the
Segment2D.reverseSegment.

transform 
public void transform(Matrix2D M)
Parameters:
M  The transforming matrix.
Processing:
Transforms the parametric curve by using the
Segment2D.transformSegment method.

clone
(abstract)

public abstract Object clone()
Returns the clone of this object.

toString
(abstract)

public abstract String toString()
Returns the string representing this object.

5. Class Rectangle2DE
return=>page top
public class Rectangle2DE extends Curve2D
Method 
Description 
Constructor 
Rectangle2DE(Segment2D[] segments)
Calls the Curve2D constructor.

Constructor

public Rectangle2DE(double x, double y, double width, double height)
Parameters:
The same as the java.awt.geom.Rectangle2D.Double.
Processing:
Creates a new Rectangle2DE object by connecting the four
Segment2D objects of LINE.

getType2DE

public int getType2DE()
Returns the constant of Curve2D.RECTANGLE.

getX

public double getX()
Same as the getX method of the java.awt.geom.Rectangle2D.
Returns the xcoordinate of the upperleft corner point of the rectangle.

getY

public double getY()
Same as the getY method of the java.awt.geom.Rectangle2D.
Returns the ycoordinate of the upperleft corner point of the rectangle.

getWidth

public double getWidth()
Same as the getWidth method of the java.awt.geom.Rectangle2D.
Returns the width of the rectangle.

getHeight

public double getHeight()
Same as the getHeight method of the java.awt.geom.Rectangle2D.
Returns the height of the rectangle.

clone

public Object clone()
Returns the clone of this object.

toString

public String toString()
Returns the string representing this object.

6. RoundRectangle2DE
return=>page top
public class RoundRectangle2DE extends Curve2D
Method 
Description 
Constructor 
RoundRectangle2DE(Segment2D[] segments)
Calls the Curve2D constructor.

Constructor

public RoundRectangle2DE(double x, double y, double width, double height,
double arcw, double arch)
Parameters:
The same as the java.awt.geom.RoundRectangle2D.Double.
Processing:
Creates a new RoundRectangle2DE object by connecting the eight Segment2D
objects of LINE and ARC.

setData 
public void setData(double x, double y, double width, double height, double
arcw, double arch)
Performs the same operation of the above constructor. 
getType2DE

public int getType2DE()
Returns the constant of Curve2D.ROUND_RECTANGLE.

getX

public double getX()
Same as the getX method of the java.awt.geom.RoundRectangle2D.
Returns the xcoordinate of the upperleft corner point of the round rectangle.

getY

public double getY()
Same as the getY method of the java.awt.geom.RoundRectangle2D.
Returns the ycoordinate of the upperleft corner point of the round rectangle.

getWidth

public double getWidth()
Same as the getWidth method of the java.awt.geom.RoundRectangle2D.
Returns the width of the round rectangle.

getHeight

public double getHeight()
Same as the getHeight method of the java.awt.geom.RoundRectangle2D.
Returns the height of the round rectangle.

getArcWidth

public double getArcWidth()
Returns the width of the arc that rounds off the corners.

getArcHeight

public double getArcHeight()
Returns the height of the arc that rounds off the corners.

clone

public Object clone()
Returns the clone of this object.

toString

public String toString()
Returns the string representing this object.

7. Ellipse2DE
return=>page top
public class Ellipse2DE extends Curve2D
Method 
Description 
Constructor 
Ellipse2DE(Segment2D[] segments)
Calls the Curve2D constructor.

Constructor

public Ellipse2DE(double x, double y, double width, double height)
Parameters:
The same as the java.awt.geom.Ellipse2D.Double.
Processing:
Creates a new Ellipse2DE object by the Segment2D
object of ARC.

getType2DE

public int getType2DE()
Returns the constant of Curve2D.ELLIPSE.

getX

public double getX()
Same as the getX method of the java.awt.geom.Ellipse2D.
Returns the xcoordinate of the upperleft corner point of the covering rectangle.

getY

public double getY()
Same as the getY method of the java.awt.geom.Ellipse2D.
Returns the ycoordinate of the upperleft corner point of the covering rectangle.

getWidth

public double getWidth()
Same as the getWidth method of the java.awt.geom.Ellipse2D.
Returns the width of the covering rectangle.

getHeight

public double getHeight()
Same as the getHeight method of the java.awt.geom.Ellipse2D.
Returns the height of the covering rectangle.

clone

public Object clone()
Returns the clone of this object.

toString

public String toString()
Returns the string representing this object.

8. Line2DE
return=>page top
public class Line2DE extends Curve2D
Method 
Description 
Constructor 
Line2DE(Segment2D[] segments)
Calls the Curve2D constructor.

Constructor

Line2DE(Point2D p1, Point2D p2)
Parameters:
The same as the java.awt.geom.Line2D.Double.
Processing:
Creates a new Line2DE object by the Segment2D
object of LINE.

getType2DE

public int getType2DE()
Returns the constant of Curve2D.LINE.

setData

public void setData(Point2D p1, Point2D p2)
Performs the same operation of the above constructor.

getP1

public Point2D getP1()
Returns the start point.

getP2

public Point2D getP2()
Returns the end point.

getX1

public double getX1()
Returns the x coordinate of the start point.

getY1

public double getY1()
Returns the y coordinate of the start point.

getX2

public double getX2()
Returns the x coordinate of the end point.

getY2

public double getY2()
Returns the y coordinate of the end point.

getTrimmedCurve2DE 
public Line2DE getTrimmedCurve2DE(double t1, double t2)
Parameters:
t1  The start parameter of the trimmed curve.
t2  The end parameter of the trimmed curve.
0≤t1, t2≤1
Returns:
The trimmed Line2DE object.

getTrimmedLine 
public Line2DE getTrimmedLine(double cut1, double cut2)
Parameters:
cut1  The cutting length (pixels) at the start point.
cut2  The cutting length (pixels) at the end point.
Returns:
The trimmed Line2DE object.
Processing:
This method uses the getTrimmedCurve2DE.

clone

public Object clone()
Returns the clone of this object.

toString

public String toString()
Returns the string representing this object.

9. Polyline2DE
return=>page top
public class Polyline2DE extends Curve2D
Method 
Description 
Constructor 
Polyline2DE(Segment2D[] segments)
Calls the Curve2D constructor.

Constructor

public Polyline2DE(Point2D[] points)
Creates a new Polyline2DE object by the junction points.
Whether this Polyline2DE is closed or not is judged by the
Curve2D.ClosedTolerance.

Constructor

public Polyline2DE(Point2D[] points, boolean closed)
Creates a new Polyline2DE object by the junction points.
Whether this Polyline2DE is closed or not is specified explicitly by the parameter.

setData

public void setData(Point2D[] points)
Performs the same operation of the above constructor.

getType2DE

public int getType2DE()
Returns the constant of Curve2D.POLYLINE.

getPoints

public Point2D[] getPoints()
Returns the junction points.

getPoint

public Point2D getPoint(int index)
Return the junction point specified by index.

getTrimmedCurve2DE

public Polyline2DE getTrimmedCurve2DE(double t1, double t2)
Parameters:
t1  The start parameter of the trimmed curve.
t2  The end parameter of the trimmed curve.
0≤t1, t2≤nseg. nseg: the returned value of the getNumOfSegments.
Returns:
The trimmed Polyline2DE object.

getTrimmedPolyline 
public Polyline2DE getTrimmedPolyline(double cut1, double cut2)
Parameters:
cut1  The cutting length (pixels) at the start point.
cut2  The cutting length (pixels) at the end point.
Returns:
The trimmed Polyline2DE object.
Processing:
This method uses the getTrimmedCurve2DE.

clone

public Object clone()
Returns the clone of this object.

toString

public String toString()
Returns the string representing this object.

10. CubicCurve2DE
return=>page top
public class CubicCurve2DE extends Curve2D
Method 
Description 
Constructor 
CubicCurve2DE(Segment2D[] segments)
Calls the Curve2D constructor.

Constructor

public CubicCurve2DE(Point2D[] Q)
Creates a new CubicCurve2DE object by the control points.
The number of the control points must be 3*n+1. Here "n" is the
number of curve segments (Segment2D objects).

setData

public void setData(Point2D[] points)
Performs the same operation of the above constructor.

getType2DE

public int getType2DE()
Returns the constant of Curve2D.CUBIC_CURVE.

getPoints

public Point2D[] getPoints()
Returns the segment junction points. The segment junction point means the junction point of the
curve segments.

getCtrlPoints

public Point2D[] getCtrlPoints()
Returns the control points.

getFergusonCurve2D

public FergusonCurve2D getFergusonCurve2D()
Converts this multiple cubic curves to the Feguson curve and returns the Feguson
curve (FergusonCurve2DE).

getTout

public Vector2D getTout(int index)
Parameter:
index  The index of the segment junction point.
Returns:
The the tangent line (OUT) at the plus side of the specified node point.

getTin

public Vector2D getTin(int index)
Paremeter:
index  The index of the segment junction point.
Returns:
The tangent line (IN) at the minus side of the specified node point.

getTrimmedCurve2DE

public CubicCurve2DE getTrimmedCurve2DE(double t1, double t2)
t1  The start parameter of the trimmed curve.
t2  The end parameter of the trimmed curve.
0≤t1, t2≤nseg. nseg: the returned value of the getNumOfSegments.
Returns:
The trimmed CubicCurve2DE object.

clone

public Object clone()
Returns the clone of this object.

toString

public String toString()
Returns the string representing this object.

11. GeneralCurve2DE
return=>page top
public class GeneralCurve2DE extends Curve2D<
This class represents a parametric curve which consists of arbitrary number of subpaths.
Figure 11.1 Global numbering of the segments and junction points
Segment number: Seg0, Seg1,..., Segment point (Junction point) number:
P0, P1,....
Figure 11.2 Local numbering of the segments and junction points
The segments and the junction points are numbered from 0 for each
sub path. 
(a) Prints out the 07 segments
segment[0]=CUBIC, P1=640.04,371.28, P2=685.90,324.95, CtrlP1=654.01,353.07,CtrlP2=665.80,324.95
segment[1]=CUBIC, P1=685.90,324.95, P2=775.45,415.98, CtrlP1=722.90,324.95, CtrlP2=738.46,415.93
segment[2]=CUBIC, P1=775.45,415.98, P2=846.18,364.98, CtrlP1=801.94,416.01, CtrlP2=831.32,406.89
segment[3]=MoveTo
segment[4]=CUBIC, P1=928.82,371.58, P2=1,004.96,328.01, CtrlP1=926.56,337.66, CtrlP2=975.82,334.84
segment[5]=CUBIC, P1=1,004.96,328.01, P2=1,085.27,382.36, CtrlP1=1,041.93,319.35, CtrlP2=1,086.01,344.76
segment[6]=CUBIC, P1=1,085.27,382.36, P2=989.42,438.44, CtrlP1=1,084.42,425.39, CtrlP2=1,029.39,455.40
segment[7]=CUBIC, P1=989.42,438.44, P2=928.82,371.58, CtrlP1=960.27,426.07, CtrlP2=931.06,405.02
(2) Prints out 07 segments in subpathform
 sub path=0, close=false, numseg=3, startSegment=0, endSegment=2 [ start tparam=0, end tparam=3 ]
segment[0]=CUBIC, P1=640.04,371.28, P2=685.90,324.95, CtrlP1=654.01,353.07, CtrlP2=665.80,324.95
segment[1]=CUBIC, P1=685.90,324.95, P2=775.45,415.98, CtrlP1=722.90,324.95, CtrlP2=738.46,415.93
segment[2]=CUBIC, P1=775.45,415.98, P2=846.18,364.98, CtrlP1=801.94,416.01, CtrlP2=831.32,406.89
 sub path=1, close=true, numseg=4, startSegment=4, endSegment=7 [ start tparam=4, end tparam=8 ]
segment[0]=CUBIC, P1=928.82,371.58, P2=1,004.96,328.01, CtrlP1=926.56,337.66, CtrlP2=975.82,334.84
segment[1]=CUBIC, P1=1,004.96,328.01, P2=1,085.27,382.36, CtrlP1=1,041.93,319.35, CtrlP2=1,086.01,344.76
segment[2]=CUBIC, P1=1,085.27,382.36, P2=989.42,438.44, CtrlP1=1,084.42,425.39, CtrlP2=1,029.39,455.40
segment[3]=CUBIC, P1=989.42,438.44, P2=928.82,371.58, CtrlP1=960.27,426.07, CtrlP2=931.06,405.02

Method 
Description 
Constructor 
GeneralCurve2DE(Segment2D[] segments)
Calls the following setData method.

setData 
public void setData(Segment2D[] segments)
Sets the segments (Segment2D objects) to this object.
For the Figure 11.1 example, sets the 8 segments
inclideing one MOVETO segment.

getType2DE

public int getType2DE()
Returns the constant of Curve2D.GENERAL_CURVE.

getNumOfSubPaths 
public int getNumOfSubPaths()
Returns the number of the subpaths of this object. Returns 2 for the Figure 11.1 example.

getNumOfLocalSegments 
public int[] getNumOfLocalSegments()
Returns each number of the segments which
configures a subpaths.
For the Figure 11.1 example, returns int[0]=3, int[0]=4, which means the
first path consists of 3 segments and the second path consists of 4 segments.

getSubPathIndex 
public int getSubPathIndex(int segmentPtIndex)
Return the subpath number for the argument which specifies a segment number
or segment joint number.
For the Figure 11.1 example, returns 0 as the subPath index for segmentPtIndex=0
 3, and returns 1 as the subPath index for segmentPtIndex=4  8.

getLocalSegmentIndex 
private int getLocalSegmentIndex(int segmentIndex)
Returns the local segment number of a sub path for the specified argument which is the global segment number.
The sub path number can be givven by getSubPathIndex method.
For the Figure 11.1 example, returns as follows.
⋅ segmentIndex=0  2 => localSegmentIndex=0  2,
⋅ segmentIndex=4  7 => localSegmentIndex=0  3,
⋅ segmentIndex=3 => localSegmentIndex=1(MOVETO segment, ineffective)

getLocalSegmentPtIndex 
public int getLocalSegmentPtIndex(int segmentPtIndex)
Returns the local segment junction point number of a sub path for the specified
argument which is the global segment junction point number. The sub path number
can be givven by getSubPathIndex method.
For the Figure 11.1 example, returns as follows.
⋅ segmentPtIndex=0  3=>localSegmentPtIndex=0  3.
⋅ segmentPtIndex=4  8=>localSegmentPtIndex=0  4.

getGlobalSegmentIndex 
private int getGlobalSegmentIndex(int subPathIndex, int localSegmentIndex)
Return the global segment number for the specified arguments which are
sub path number and the local segment number. For the Figure 11.1 example, returns as follows.
⋅ subPathIndex=0, localSegmentIndex=0  2 => globalSegmentIndex=0  2.
⋅ subPathIndex=1, localSegmentIndex=0  3 => globalSegmentIndex=4 
7.
⋅ return 1 (ineffective) except the aboves.

getGlobalSegmentPtIndex 
public int getGlobalSegmentPtIndex(int subPathIndex, int localSegmentPtIndex)
Return the global segment junction point number for the specified arguments which are sub path number and the local segment junction point number.
For the Figure 11.1 example, returns as follows.
⋅ subPathIndex=0, localSegmentPtIndex=0  3 => globalSegmentPtIndex=0
 3.
⋅ subPathIndex=1, localSegmentPtIndex=0  4 => globalSegmentPtIndex=4
 8.
⋅ return 1 (ineffective) except the aboves.

getSubPathSegments 
private Segment2D[] getSubPathSegments(int subPathIndex)
Returns the segments which belong to the sub path specified by argument.
For the Figure 11.1 example, returns as follows.
⋅ subPathInde=0 => returns 0  2 segments.
⋅ subPathInde=1 => returns 4 7 segments.

getSubPath 
private GeneralCurve2DE getSubPath(int index)
Returns the sub path curve as a GeneralCurve2DE object for the specified
argument which is sub path number. For the Figure 11.1 example, returns as follows.
⋅ subPathInde=0 => GeneralCurve2DE object which consists of 0 
2 segments.
⋅ subPathInde=1 => GeneralCurve2DE object which consists of ４  7 segments.

getSubPaths 
public GeneralCurve2DE[] getSubPaths()
Returns the array the sub paths which are represented as GeneralCurve2DE objects.

setSubPaths 
public void setSubPaths(Curve2D[] curves)
Specifies the plural sub paths as the arguments
and sets them to this object.
⋅ Checks the connections between the specified sub paths by the
PathConnect class, and connects them if possible.

isClosed 
public boolean isClosed()
Return true, if the sub path of this object is only one
and it is closed. Returns false for the othe case.
To confirm closed or not closed for each subpath, use getPaths method and
inquire by isClosed method of each sub path object.

getTrimmedCurve2DE

public CubicCurve2DE getTrimmedCurve2DE(double t1, double t2)
t1  The start parameter of the trimmed curve.
t2  The end parameter of the trimmed curve.
0≤t1, t2≤nseg. nseg: the returned value of the getNumOfSegments.
Returns:
The trimmed GeneralCurve2DE object.

getSimpleCurve2Ds 
public Curve2D[] getSimpleCurve2Ds()

getSimpleCurve2D 
public Curve2D getSimpleCurve2D()
Returns:
The Curve2DE object of simpler form.
Processing:
If this GeneralCurve2DE can be converted to Line2DE,Polyline2DE or CubicCurve2DE,
then converts the GeneralCurve2DE to simpler form and returns it.

clone

public Object clone()
Returns the clone of this object.

toString

public String toString()
Returns the string representing this object.

12. FergusonCurve2D
return=>page top
public class FergusonCurve2D
This class is not a extended class of the Curve2D and it represents the Ferguson curve.
The Ferguson curve is convenient for handling the tangent vectors of the curve segment because
the tangent vectors are expressed explicitly.
Figure 12.1 Ferguson curve
=> The definition of Tin, Tout
Field 
Description 
P

Point2D[] P
The array of the segment junction points.

Tin 
Vector2D[] Tin
The array of the tangent vectors at the segment junction points which interpolate
the next curve segments.
=>
Ferguson curve segment on this page

Tout 
Vector2D[] Tout
The array of the tangent vectors at the segment junction points which interpolate the
previous curve segments.
=>
Ferguson curve segment on this page

closed 
boolean closed
True if the curve is closed.

pai 
static double pai=Math.PI
The circle ratio.

eps 
static double eps=1e12
The small number. 
TIN, TOUT 
public static final int TIN=0, TOUT=1 
Method 
Description 
Constructor

public FergusonCurve2D()
Creates a new object that has no curve data.

Constructor

public FergusonCurve2D(Point2D[] P, Vector2D[] Tin, Vector2D[] Tout)
Parameters:
P  The array of the segment junction points.
Tin  The array of the tangent vectors at the segment junction points which interpolate the next curve segments
Tout  The array of the tangent vectors at the segment junction points which interpolate
the previous curve segments.
Processing:
Sets the parameters to corresponding fields.
If P[0}=P[np1], then sets true to the closed field.
np: the number of the segment junction points.

isClosed

public boolean isClosed()
Return the closed field.

getNumOfSegments

public int getNumOfCSegments()
Returns the number of the curve segments.

getCubicCurve2DE

public CubicCurve2DE getCubicCurve2DE()
Returns the CubicCurve2DE object which is converted from this object.

getCubicCurve2D

public CubicCurve2D getCubicCurve2D(int index)
Returns the java.awt.geom.CubicCurve2D object which is converted from the
curve segment of this object specified by the index.

getCtrlPoints

public Point2D[] getCtrlPoints()
Converts this FergusonCurve2D object to the CubicCurve2DE
object and returns the control points of the CubicCurve2DE.
The number of the control points is (3×(np1)+1).
np: the number of the segment junction points.

getP

public Point2D getP(int index)
Returns the segment junction point specified by the index.

setP

public void setP(Point2D P, int index)
Sets the point P to the P at the position specified by the index.

getTin

public Vector2D getTin(int index)
Returns the Tin (tangent vector) specified by the index.

setTin

public void setTin(Vector2D Tin, int index)
Sets the tangent vector Tin to the Tin
at the position specified by the index..

getTout

public Vector2D getTout(int index)
Returns the Tout (tangent vector) specified by the index.

setTout

public void setTout(Vector2D Tout, int index)
Sets the tangent vector Tout to the Tout
at the position specified by the index.

getP

public Point2D getP(double t)
Returns the point on the Fergusn curve specified by t.

getTangent

public Vector2D getTangent(double t)
Returns the tangent vector on the Fergusn curve specified by t.

movePoint

public void movePoint(int index, Point2D newPoint)
Paremeters:
index  The index of the segment junction point to be moved.
newPoint  the new segment junction point.
Processing:
Replace the segment junction point (P[index]) by the newPoint.
The directions of the Tout[index1],
Tin[index], Tout[index] and
Tin[index+1] are not changed,
however the lengths of those vectors are optimized
by the getOptimizedTangents method.

moveTangent

public void moveTangent(int index, Vector2D newTangent)
Paremeters:
index  The index of the segment junction point.
newTangent  The new tangent vector.
The direction of the newTangent will be referred (the length isn't referred).
Processing:
Replaces the direction of the Tin[index],
Tout[index] by the newTangent.
The lengths of the Tout[index1],
Tin[index], Tout[index]
and Tin[index+1] are optimized by the
getOptimizedTangents method.

addPoint

public void addPoint(double t)
Parameters:
t  The curve parameter of the point to be added.
Processing:
Adds the segment junction point at the parameter of t.
Let's define as it= (int)t, then the new segment junction point is indicated by the index of
(it+1).
The point and the Tin, Tout at t can be calculated by the getP and the getTangent, so by adding these data to P[it+1], Tin[it+1] and Tout[it+1], the new Ferguson curve will be created.
However the length of the Tout[it],
Tin[it+1], Tout[it+1]
and Tin[it+2] must be changed
so that any point on the new curve lies on the original curve.
The formulas of the new lengths are the follows.
⋅ The lengths of Tout[it], Tin[it+1]：Provided by the formula of (tit)*(the original length).
⋅ The lengths of Tout[it+1], Tin[it+2]：Provided by the formula of (i+1t)*(the original length).

deletePoint

public void deletePoint(int index)
Parameters:
index  The index of the segment junction point to be delete.
Processing:
Deletes the P[index], Tin[index] and Tout[index] and creates a new curve.
If the original curve is closed, then the new curve must be closed.

toString

public String toString()
Return the string representing this object.

createNaturalSpline
(static)

public static FergusonCurve2D createNaturalSpline(Point2D[] nodePTs)
Paremeters:
nodePTs  The segment junction points of the spline
Returns:
The C^{2} class spline curve of Furguson curve format.
Processing:
Creates the C^{2} class spline curve which passes the given segment junction points (nodePTs).
⋅ If the start point and the end point of the given points doesn't occupy
the same location, then performs the following.
Calls the getUnitTangentOfOpenCurve method
to determine the tangent directions at the given points for a open (not closed) spline.
⋅ If the start point and the end point of the given points occupies the
same location, then performs the following.
Calls the getUnitTangentOfOpenCurve method
to determine the tangent directions at the given points for a closed spline.
The length of the tangent vectors are determined by the the
Curve2DUtil.createCircularArcs method.

getUnitTangentOf
OpenCurve
(static)

public static Vector2D[] getUnitTangentOfOpenCurve(Point2D[] nodePTs)
Parameters:
nodePTs  The segment junction points of the spline.
Returns:
The unit tangent vectors at the nodePTs.
Processing:
Solves the linear equation by the Matrix.GaussianElimination method.
The linear equation is created by the condition of the C^{2} class continuity of the spline
at each segment junction point.
The tangent vectors at the start node and the end node are calculated by the the
Curve2DUtil.createCircularArcs method .

getUnitTangentOf
ClosedCurve
(static)

public static Vector2D[] getUnitTangentOfClosedCurve(Point2D[] nodePTs)
Parameters:
nodePTs  The segment junction points of the spline.
Returns:
The unit tangent vectors at the nodePTs.
Processing:
Solves the linear equation by the Matrix.GaussianElimination method.
The linear equation is created by the condition of the C^{2} class continuity
of the spline at each segment junction point.

getOptimizedTangents
(static)

public static Vector2D[] getOptimizedTangents(Point2D P0, Point2D P1, Vector2D
Tout, Vector2D Tin)
Parameters:
P0  The first segment junction point.
P1  The second segment junction point.
Tout  The first tangent vector.
Tin  The second tangent vector.
Returns:
The new Tout, Tin vectors.
This method changes the lengths of the Tout and Tin without changing their directions.
Processing:
The notations in the figure below are as follows.
⋅ The line of P0,Q0: The normal line of the Tout.
⋅ The line of P1,Q1: The normal line of the Tin.
⋅ P01: The middle point of P0, P1.
⋅ The line of P01, Q1: The normal line of the line of P0, P1.
The optimized vector length Tout, Tin are calculated as follows.
Tout=4.0*r0*(1cos(teta0))/sin(teta0)
Tin =4.0*r1*(1cos(teta1))/sin(teta1)
:
If the Tout and Tin are parallel, then the lengths of Tout and Tin are the same as
the line length of P0, P1.

