Class 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.
    • 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​(PdfCanvas canvas)
      Draws this instruction to a canvas object.
      private static 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 point
      void 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 java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • 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 coordinates
        previous - 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​(PdfCanvas canvas)
        Description copied from interface: IPathShape
        Draws this instruction to a canvas object.
        Parameters:
        canvas - to which this instruction is drawn
      • 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 list
        rotation - the rotation angle, in radians
        rotator - 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)
      • 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 Method getEllipseCenterCoordinates(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 method getEllipseCenterCoordinates(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. Method isPointOnTheArc(double, double, double, boolean).
        Parameters:
        x1 - x coordinate of the starting point
        y1 - y coordinate of the starting point
        rx - x radius
        ry - y radius
        phi - x-axis rotation
        largeArc - 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" direction
        x2 - x coordinate of ending point
        y2 - 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 point
        y1 - y coordinate of the starting point
        rx - x radius
        ry - y radius
        phi - x-axis rotation
        largeArc - large arc flag
        sweep - sweep flag
        x2 - x coordinate of ending point
        y2 - 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 radius
        ry - y radius
        phi - x-axis rotation
        cx - x coordinate of ellipse center
        cy - 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 check
        angle1 - 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 point
        by - y coordinate of the vector ending point
        Returns:
        calculated angle between vectors
      • anglesAreEquals

        private boolean anglesAreEquals​(double angle1,
                                        double angle2)