internal void ArcFor(PDFUnit rx, PDFUnit ry, double ang, PathArcSize size, PathArcSweep sweep, PDFPoint enddelta)
        {
            PDFPoint    end = ConvertDeltaToActual(enddelta);
            PathArcData arc = new PathArcData()
            {
                RadiusX = rx, RadiusY = ry, XAxisRotation = ang, ArcSize = size, ArcSweep = sweep, EndPoint = end
            };

            CurrentPath.Add(arc);

            IEnumerable <PathBezierCurveData> curves = PathDataHelper.GetBezierCurvesForArc(this.Cursor, arc);

            foreach (PathBezierCurveData bez in curves)
            {
                IncludeInBounds(bez.EndPoint);
                if (bez.HasStartHandle)
                {
                    IncludeInBounds(bez.StartHandle);
                }
                if (bez.HasEndHandle)
                {
                    IncludeInBounds(bez.EndHandle);
                }
            }

            Cursor = end;
        }
        internal static IEnumerable <PathBezierCurveData> GetBezierCurvesForArc(PDFPoint start, PathArcData arc)
        {
            List <PathBezierCurveData> all = new List <PathBezierCurveData>();

            try
            {
                if (start == arc.EndPoint)
                {
                    return(all);
                }

                if (arc.RadiusX == 0.0f && arc.RadiusY == 0.0f)
                {
                    PathBezierCurveData data = new PathBezierCurveData(arc.EndPoint, start, arc.EndPoint, false, false);
                    all.Add(data);
                    return(all);
                }

                double sinPhi = Math.Sin(arc.XAxisRotation.PointsValue * PathDataHelper.RadiansPerDegree);
                double cosPhi = Math.Cos(arc.XAxisRotation.PointsValue * PathDataHelper.RadiansPerDegree);

                double x1dash = cosPhi * (start.X.PointsValue - arc.EndPoint.X.PointsValue) / 2.0 + sinPhi * (start.Y.PointsValue - arc.EndPoint.Y.PointsValue) / 2.0;
                double y1dash = -sinPhi * (start.X.PointsValue - arc.EndPoint.X.PointsValue) / 2.0 + cosPhi * (start.Y.PointsValue - arc.EndPoint.Y.PointsValue) / 2.0;

                double root;
                double numerator = arc.RadiusX.PointsValue * arc.RadiusX.PointsValue * arc.RadiusY.PointsValue * arc.RadiusY.PointsValue
                                   - arc.RadiusX.PointsValue * arc.RadiusX.PointsValue * y1dash * y1dash
                                   - arc.RadiusY.PointsValue * arc.RadiusY.PointsValue * x1dash * x1dash;

                double rx = arc.RadiusX.PointsValue;
                double ry = arc.RadiusY.PointsValue;

                if (numerator < 0.0)
                {
                    double s = (double)Math.Sqrt(1.0 - numerator / (arc.RadiusX.PointsValue * arc.RadiusX.PointsValue * arc.RadiusY.PointsValue * arc.RadiusY.PointsValue));

                    rx  *= s;
                    ry  *= s;
                    root = 0.0;
                }
                else
                {
                    root = ((arc.ArcSize == PathArcSize.Large && arc.ArcSweep == PathArcSweep.Positive) || (arc.ArcSize == PathArcSize.Small && arc.ArcSweep == PathArcSweep.Negative) ? -1.0 : 1.0)
                           * Math.Sqrt(numerator / (arc.RadiusX.PointsValue * arc.RadiusX.PointsValue * y1dash * y1dash + arc.RadiusY.PointsValue * arc.RadiusY.PointsValue * x1dash * x1dash));
                }

                double cxdash = root * rx * y1dash / ry;
                double cydash = -root * ry * x1dash / rx;

                double cx = cosPhi * cxdash - sinPhi * cydash + (start.X.PointsValue + arc.EndPoint.X.PointsValue) / 2.0;
                double cy = sinPhi * cxdash + cosPhi * cydash + (start.Y.PointsValue + arc.EndPoint.Y.PointsValue) / 2.0;


                double theta1 = PathDataHelper.CalculateVectorAngle(1.0, 0.0, (x1dash - cxdash) / rx, (y1dash - cydash) / ry);
                double dtheta = PathDataHelper.CalculateVectorAngle((x1dash - cxdash) / rx, (y1dash - cydash) / ry, (-x1dash - cxdash) / rx, (-y1dash - cydash) / ry);

                if (arc.ArcSweep == PathArcSweep.Negative && dtheta > 0)
                {
                    dtheta -= 2.0 * Math.PI;
                }
                else if (arc.ArcSweep == PathArcSweep.Positive && dtheta < 0)
                {
                    dtheta += 2.0 * Math.PI;
                }

                int    segments = (int)Math.Ceiling((double)Math.Abs(dtheta / (Math.PI / 2.0)));
                double delta    = dtheta / segments;
                double t        = 8.0 / 3.0 * Math.Sin(delta / 4.0) * Math.Sin(delta / 4.0) / Math.Sin(delta / 2.0);

                double startX = start.X.PointsValue;
                double startY = start.Y.PointsValue;


                for (int i = 0; i < segments; ++i)
                {
                    double cosTheta1 = Math.Cos(theta1);
                    double sinTheta1 = Math.Sin(theta1);
                    double theta2    = theta1 + delta;
                    double cosTheta2 = Math.Cos(theta2);
                    double sinTheta2 = Math.Sin(theta2);

                    double endpointX = cosPhi * rx * cosTheta2 - sinPhi * ry * sinTheta2 + cx;
                    double endpointY = sinPhi * rx * cosTheta2 + cosPhi * ry * sinTheta2 + cy;

                    double dx1 = t * (-cosPhi * rx * sinTheta1 - sinPhi * ry * cosTheta1);
                    double dy1 = t * (-sinPhi * rx * sinTheta1 + cosPhi * ry * cosTheta1);

                    double dxe = t * (cosPhi * rx * sinTheta2 + sinPhi * ry * cosTheta2);
                    double dye = t * (sinPhi * rx * sinTheta2 - cosPhi * ry * cosTheta2);

                    PDFPoint endPoint    = new PDFPoint(endpointX, endpointY);
                    PDFPoint startHandle = new PDFPoint((startX + dx1), (startY + dy1));
                    PDFPoint endHandle   = new PDFPoint((endpointX + dxe), (endpointY + dye));

                    PathBezierCurveData bezier = new PathBezierCurveData(endPoint, startHandle, endHandle, true, true);
                    all.Add(bezier);

                    theta1 = theta2;
                    startX = (float)endpointX;
                    startY = (float)endpointY;
                }
            }
            catch (Exception ex)
            {
                throw new PDFException(Errors.CouldNotBuildPathFromArc, ex);
            }

            return(all);
        }
Exemple #3
0
        private void RenderPathOp(PathData data, PDFPoint location, ref PDFPoint cursor)
        {
            switch (data.Type)
            {
            case PathDataType.Move:
                PathMoveData move = (PathMoveData)data;
                cursor = move.MoveTo;
                this.RenderMoveTo(move.MoveTo.X + location.X, move.MoveTo.Y + location.Y);
                break;

            case PathDataType.Line:
                PathLineData line = (PathLineData)data;
                cursor = line.LineTo;
                this.RenderLineTo(line.LineTo.X + location.X, line.LineTo.Y + location.Y);
                break;

            case PathDataType.Rect:
                PathRectData rect = (PathRectData)data;
                cursor = rect.Rect.Location;
                this.RenderRectangle(rect.Rect.X + location.X, rect.Rect.Y + location.Y, rect.Rect.Width, rect.Rect.Height);
                break;

            case PathDataType.SubPath:
                PathSubPathData sub = (PathSubPathData)data;
                this.RenderPathData(location, sub.InnerPath, ref cursor);
                break;

            case PathDataType.Bezier:
                PathBezierCurveData bez = (PathBezierCurveData)data;
                cursor = bez.EndPoint;
                if (bez.HasStartHandle && bez.HasEndHandle)
                {
                    this.RenderBezierCurveTo(bez.EndPoint.X + location.X, bez.EndPoint.Y + location.Y,
                                             bez.StartHandle.X + location.X, bez.StartHandle.Y + location.Y,
                                             bez.EndHandle.X + location.X, bez.EndHandle.Y + location.Y);
                }
                else if (bez.HasStartHandle)
                {
                    this.RenderBezierCurveToWithStartHandleOnly(bez.EndPoint.X + location.X, bez.EndPoint.Y + location.Y,
                                                                bez.StartHandle.X + location.X, bez.StartHandle.Y + location.Y);
                }
                else if (bez.HasEndHandle)
                {
                    this.RenderBezierCurveToWithEndHandleOnly(bez.EndPoint.X + location.X, bez.EndPoint.Y + location.Y,
                                                              bez.EndHandle.X + location.X, bez.EndHandle.Y + location.Y);
                }
                else
                {
                    this.RenderLineTo(bez.Points[2].X, bez.Points[2].Y);
                }

                break;

            case PathDataType.Arc:
                IEnumerable <PathBezierCurveData> segments;
                PathArcData arc = (PathArcData)data;
                segments = PathDataHelper.GetBezierCurvesForArc(cursor, arc);
                foreach (PathBezierCurveData segment in segments)
                {
                    this.RenderBezierCurveTo(segment.EndPoint.X + location.X,
                                             segment.EndPoint.Y + location.Y,
                                             segment.StartHandle.X + location.X,
                                             segment.StartHandle.Y + location.Y,
                                             segment.EndHandle.X + location.X,
                                             segment.EndHandle.Y + location.Y);
                }
                cursor = arc.EndPoint;
                break;

            case PathDataType.Quadratic:
                IEnumerable <PathBezierCurveData> quadSegments;
                PathQuadraticCurve quad = (PathQuadraticCurve)data;
                quadSegments = PathDataHelper.GetBezierCurvesForQuadratic(cursor, quad);
                foreach (PathBezierCurveData quadSeg in quadSegments)
                {
                    this.RenderBezierCurveTo(quadSeg.EndPoint.X + location.X, quadSeg.EndPoint.Y + location.Y,
                                             quadSeg.StartHandle.X + location.X, quadSeg.StartHandle.Y + location.Y,
                                             quadSeg.EndHandle.X + location.X, quadSeg.EndHandle.Y + location.Y);
                }
                cursor = quad.EndPoint;
                break;

            case PathDataType.Close:
                this.RenderClosePathOp();
                cursor = PDFPoint.Empty;
                break;

            default:
                throw new ArgumentOutOfRangeException("data.Type");
            }
        }