Class EllipticalCurveTo
- java.lang.Object
-
- com.itextpdf.svg.renderers.path.impl.AbstractPathShape
-
- com.itextpdf.svg.renderers.path.impl.EllipticalCurveTo
-
- All Implemented Interfaces:
IPathShape
public class EllipticalCurveTo extends AbstractPathShape
Implements elliptical curveTo (A) segment of SVG's path element. Implemented in PDF as Bézier curves. Edge cases & value correction below always refer to https://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes For some calculations we need double precision floating point math, so we have forced all calculations to use double. However, float comparison is used instead of double comparison, because close coordinates can be considered equal.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) static class
EllipticalCurveTo.EllipseArc
Converts between two types of definitions of an arc: The input is an arc defined by two points and the two semi-axes of the ellipse.
-
Field Summary
Fields Modifier and Type Field Description (package private) static int
ARGUMENT_SIZE
private static double
EPS
private Point
startPoint
-
Fields inherited from class com.itextpdf.svg.renderers.path.impl.AbstractPathShape
context, coordinates, copier, properties, relative
-
-
Constructor Summary
Constructors Constructor Description EllipticalCurveTo()
Creates an absolute Elliptical curveTo.EllipticalCurveTo(boolean relative)
Creates a Elliptical curveTo.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description private boolean
anglesAreEquals(double angle1, double angle2)
void
draw()
Draws this instruction to a canvas object.private void
drawCurve(PdfCanvas canvas, Point cp1, Point cp2, Point end)
private double
getAngleBetweenVectors(double bx, double by)
Return the angle between the vector (1, 0) and the line specified by points (0, 0) and (bx, by) in range [ 0, Pi/2 ] U [ 3*Pi/2, 2*Pi).private double
getCoordinate(int index)
(package private) java.lang.String[]
getCoordinates()
private double[]
getEllipseCenterCoordinates(double x1, double y1, double rx, double ry, double phi, boolean largeArc, boolean sweep, double x2, double y2)
Calculate the center coordinates of the whole ellipse.private double[]
getEllipticalArcMinMaxPoints(double x1, double y1, double rx, double ry, double phi, boolean largeArc, boolean sweep, double x2, double y2)
Algorithm to find elliptical arc bounding box: 1.private double[][]
getExtremeCoordinatesAndAngles(double rx, double ry, double phi, double cx, double cy)
Calculate extremes of the ellipse function and corresponding angles.Rectangle
getPathShapeRectangle(Point lastPoint)
Get bounding rectangle of the current path shape.private boolean
isPointOnTheArc(double pointAngle, double angle1, double angle2, boolean otherArc)
Check that angle corresponding to extreme points is on the current arc.private Point[][]
makePoints(java.util.List<double[]> input)
(package private) static Point[][]
rotate(Point[][] list, double rotation, Point rotator)
This convenience method rotates a given set of points around a given pointvoid
setCoordinates(java.lang.String[] inputCoordinates, Point previous)
This method sets the coordinates for the path painting operator and does internal preprocessing, if necessary-
Methods inherited from class com.itextpdf.svg.renderers.path.impl.AbstractPathShape
applyTransform, createPoint, draw, getEndingPoint, isRelative, parseHorizontalLength, parseVerticalLength, setContext, setParent, setTransform
-
-
-
-
Field Detail
-
ARGUMENT_SIZE
static final int ARGUMENT_SIZE
- See Also:
- Constant Field Values
-
startPoint
private Point startPoint
-
EPS
private static final double EPS
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
EllipticalCurveTo
public EllipticalCurveTo()
Creates an absolute Elliptical curveTo.
-
EllipticalCurveTo
public EllipticalCurveTo(boolean relative)
Creates a Elliptical curveTo. Set argument to true to create a relative EllipticalCurveTo.- Parameters:
relative
- whether this is a relative EllipticalCurveTo or not
-
-
Method Detail
-
setCoordinates
public void setCoordinates(java.lang.String[] inputCoordinates, Point previous)
Description copied from interface:IPathShape
This method sets the coordinates for the path painting operator and does internal preprocessing, if necessary- Parameters:
inputCoordinates
- an array containing point values for path coordinatesprevious
- the ending point of the previous operator, or, in broader terms, the point that the coordinates should be absolutized against, for relative operators
-
draw
public void draw()
Description copied from class:AbstractPathShape
Draws this instruction to a canvas object.- Specified by:
draw
in classAbstractPathShape
-
rotate
static Point[][] rotate(Point[][] list, double rotation, Point rotator)
This convenience method rotates a given set of points around a given point- Parameters:
list
- the input listrotation
- the rotation angle, in radiansrotator
- the point to rotate around- Returns:
- the list of rotated points
-
getCoordinates
java.lang.String[] getCoordinates()
-
makePoints
private Point[][] makePoints(java.util.List<double[]> input)
-
getPathShapeRectangle
public Rectangle getPathShapeRectangle(Point lastPoint)
Description copied from class:AbstractPathShape
Get bounding rectangle of the current path shape.- Specified by:
getPathShapeRectangle
in interfaceIPathShape
- Overrides:
getPathShapeRectangle
in classAbstractPathShape
- Parameters:
lastPoint
- start point for this shape- Returns:
- calculated rectangle
-
getCoordinate
private double getCoordinate(int index)
-
getEllipticalArcMinMaxPoints
private double[] getEllipticalArcMinMaxPoints(double x1, double y1, double rx, double ry, double phi, boolean largeArc, boolean sweep, double x2, double y2)
Algorithm to find elliptical arc bounding box: 1. Compute extremes using parametric description of the whole ellipse We use parametric description of ellipse: x(theta) = cx + rx*cos(theta)*cos(phi) - ry*sin(theta)*sin(phi) y(theta) = cy + rx*cos(theta)*sin(phi) + ry*sin(theta)*cos(phi) After obtaining the derivative and equating it to zero, we get two solutions for x: theta = -atan(ry*tan(phi)/rx) and theta = M_PI -atan(ry*tan(phi)/rx) and two solutions for y: theta = atan(ry/(tan(phi)*rx)) and theta = M_PI + atan(ry/(tan(phi)*rx)) Then to get theta values we need to know cx and cy - the coordinates of the center of the ellipse. 2. Compute the center of the ellipse MethodgetEllipseCenterCoordinates(double, double, double, double, double, boolean, boolean, double, double)
3. Determine the bounding box of the whole ellipse When we know cx and cy values we can get the bounding box of whole ellipse. That done in the methodgetEllipseCenterCoordinates(double, double, double, double, double, boolean, boolean, double, double)
. 4. Find tightest possible bounding box Check that given points is on the arc using polar coordinates of points. MethodisPointOnTheArc(double, double, double, boolean)
.- Parameters:
x1
- x coordinate of the starting pointy1
- y coordinate of the starting pointrx
- x radiusry
- y radiusphi
- x-axis rotationlargeArc
- large arc flag. If this is true, then one of the two larger arc sweeps will be chosen (greater than or equal to 180 degrees)sweep
- sweep flag. If sweep flag is true, then the arc will be drawn in a "positive-angle" direction and if false - in a "negative-angle" directionx2
- x coordinate of ending pointy2
- y coordinate of ending point- Returns:
- array of {xMin, yMin, xMax, yMax} values
-
getEllipseCenterCoordinates
private double[] getEllipseCenterCoordinates(double x1, double y1, double rx, double ry, double phi, boolean largeArc, boolean sweep, double x2, double y2)
Calculate the center coordinates of the whole ellipse. Also return rx, ry values since they can be changed in this method. Algorithm for calculation centre coordinates: https://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter- Parameters:
x1
- x coordinate of the starting pointy1
- y coordinate of the starting pointrx
- x radiusry
- y radiusphi
- x-axis rotationlargeArc
- large arc flagsweep
- sweep flagx2
- x coordinate of ending pointy2
- y coordinate of ending point- Returns:
- the array of {cx, cy, rx, ry} values
-
getExtremeCoordinatesAndAngles
private double[][] getExtremeCoordinatesAndAngles(double rx, double ry, double phi, double cx, double cy)
Calculate extremes of the ellipse function and corresponding angles. Angles are calculated relative to the center of the ellipse.- Parameters:
rx
- x radiusry
- y radiusphi
- x-axis rotationcx
- x coordinate of ellipse centercy
- y coordinate of ellipse center- Returns:
- array of extreme coordinate and array of angles corresponding to these coordinates.
-
isPointOnTheArc
private boolean isPointOnTheArc(double pointAngle, double angle1, double angle2, boolean otherArc)
Check that angle corresponding to extreme points is on the current arc. For this we check that this angle is between the angles of starting and ending points.- Parameters:
pointAngle
- angle to checkangle1
- angle of the first extreme point if ellipse(starting or ending)angle2
- angle of the second extreme point if ellipse(starting or ending)otherArc
- if we should check that point is placed on the other arc of the current ellipse- Returns:
- true if point is on the arc
-
getAngleBetweenVectors
private double getAngleBetweenVectors(double bx, double by)
Return the angle between the vector (1, 0) and the line specified by points (0, 0) and (bx, by) in range [ 0, Pi/2 ] U [ 3*Pi/2, 2*Pi). As the angle between vectors should cover the whole circle, i.e. [0, 2* Pi). General formula to find angle between two vectors is formula F.6.5.4 on the https://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter.- Parameters:
bx
- x coordinate of the vector ending pointby
- y coordinate of the vector ending point- Returns:
- calculated angle between vectors
-
anglesAreEquals
private boolean anglesAreEquals(double angle1, double angle2)
-
-