Esempio n. 1
0
        /// <summary>
        /// Generate polygon from path
        /// </summary>
        /// <param name="path">path</param>
        /// <param name="averageScale">average scale of transform, this to decrease number of point generate for curve ...</param>
        /// <returns></returns>
        public double[][] Generate(DrawingPath path, double averageScale)
        {
            RawPolygonList polygonList = new RawPolygonList();

            DrawingPathCommand[] commands = path.Commands;
            double[] coordinates = path.Coordinates;
            int commandCount = path.CommandCount;
            int coordinateCount = path.CoordinateCount;
            int coordinateIndex = 0;
            //foreach(PathCommand command in commands)
            for (int commandIndex = 0; commandIndex < commandCount; commandIndex++)
            {
                switch (commands[commandIndex])
                {
                    case DrawingPathCommand.MoveTo:
                    case DrawingPathCommand.NewFigure:
                        #region move to
                        if (path.Commands[commandIndex + 1] == DrawingPathCommand.ArcTo)
                        {
                            coordinateIndex += 2;
                            break;
                        }
                        polygonList.MoveTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]);
                        break;
                        #endregion
                    case DrawingPathCommand.NewFigureAndCloseLast:
                        #region close last and new figure
                        // close last
                        polygonList.CloseCurrentPolygon();
                        // move to
                        polygonList.MoveTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]);
                        break;
                        #endregion
                    case DrawingPathCommand.LineTo:
                        #region line to
                        polygonList.LineTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]);
                        #endregion
                        break;
                    case DrawingPathCommand.ArcTo:
                        #region arc to
                        BuildArc(polygonList,
                        coordinates[coordinateIndex - 2], // start x
                        coordinates[coordinateIndex - 1], // start y
                        coordinates[coordinateIndex++], // radius x
                        coordinates[coordinateIndex++], // radius y
                        coordinates[coordinateIndex++], // angle
                        coordinates[coordinateIndex++] == DrawingPath.IsLargeArc,      // is large arc
                        coordinates[coordinateIndex++] == DrawingPath.IsSweepLeftSide, // is sweep left side
                        coordinates[coordinateIndex++], // dest x
                        coordinates[coordinateIndex++], // dest y
                        averageScale);
                        #endregion

                        break;

                    case DrawingPathCommand.CurveTo:
                        #region curve to
                        BuildCurve(polygonList,
                        coordinates[coordinateIndex - 2],   // start x
                        coordinates[coordinateIndex - 1],   // start y
                        coordinates[coordinateIndex++],     // control point 1 x
                        coordinates[coordinateIndex++],     // control point 1 y
                        coordinates[coordinateIndex++],     // control point 2 x
                        coordinates[coordinateIndex++],     // control point 2 y
                        coordinates[coordinateIndex++],     // end x
                        coordinates[coordinateIndex++],     // end y
                        averageScale);
                        #endregion
                        break;

                    case DrawingPathCommand.QuadraticTo:
                        #region quadratic bezier
                        BuildQuadratic(polygonList,
                        coordinates[coordinateIndex - 2],   // start x
                        coordinates[coordinateIndex - 1],   // start y
                        coordinates[coordinateIndex++],     // control point x
                        coordinates[coordinateIndex++],     // control point y
                        coordinates[coordinateIndex++],     // end x
                        coordinates[coordinateIndex++],     // end y
                        averageScale);
                        #endregion
                        break;
                }
            }

            // finish generation
            polygonList.Finish();
            return polygonList.RawDatas;
        }
Esempio n. 2
0
        /// <summary>
        /// Generate polygon from path
        /// </summary>
        /// <param name="path">path</param>
        /// <param name="averageScale">average scale of transform, this to decrease number of point generate for curve ...</param>
        /// <returns></returns>
        public double[][] Generate(DrawingPath path, double averageScale)
        {
            RawPolygonList polygonList = new RawPolygonList();

            DrawingPathCommand[] commands    = path.Commands;
            double[]             coordinates = path.Coordinates;
            int commandCount    = path.CommandCount;
            int coordinateCount = path.CoordinateCount;
            int coordinateIndex = 0;

            //foreach(PathCommand command in commands)
            for (int commandIndex = 0; commandIndex < commandCount; commandIndex++)
            {
                switch (commands[commandIndex])
                {
                case DrawingPathCommand.MoveTo:
                case DrawingPathCommand.NewFigure:
                    #region move to
                    if (path.Commands[commandIndex + 1] == DrawingPathCommand.ArcTo)
                    {
                        coordinateIndex += 2;
                        break;
                    }
                    polygonList.MoveTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]);
                    break;

                    #endregion
                case DrawingPathCommand.NewFigureAndCloseLast:
                    #region close last and new figure
                    // close last
                    polygonList.CloseCurrentPolygon();
                    // move to
                    polygonList.MoveTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]);
                    break;

                    #endregion
                case DrawingPathCommand.LineTo:
                    #region line to
                    polygonList.LineTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]);
                    #endregion
                    break;

                case DrawingPathCommand.ArcTo:
                    #region arc to
                    BuildArc(polygonList,
                             coordinates[coordinateIndex - 2],                              // start x
                             coordinates[coordinateIndex - 1],                              // start y
                             coordinates[coordinateIndex++],                                // radius x
                             coordinates[coordinateIndex++],                                // radius y
                             coordinates[coordinateIndex++],                                // angle
                             coordinates[coordinateIndex++] == DrawingPath.IsLargeArc,      // is large arc
                             coordinates[coordinateIndex++] == DrawingPath.IsSweepLeftSide, // is sweep left side
                             coordinates[coordinateIndex++],                                // dest x
                             coordinates[coordinateIndex++],                                // dest y
                             averageScale);
                    #endregion

                    break;

                case DrawingPathCommand.CurveTo:
                    #region curve to
                    BuildCurve(polygonList,
                               coordinates[coordinateIndex - 2], // start x
                               coordinates[coordinateIndex - 1], // start y
                               coordinates[coordinateIndex++],   // control point 1 x
                               coordinates[coordinateIndex++],   // control point 1 y
                               coordinates[coordinateIndex++],   // control point 2 x
                               coordinates[coordinateIndex++],   // control point 2 y
                               coordinates[coordinateIndex++],   // end x
                               coordinates[coordinateIndex++],   // end y
                               averageScale);
                    #endregion
                    break;

                case DrawingPathCommand.QuadraticTo:
                    #region quadratic bezier
                    BuildQuadratic(polygonList,
                                   coordinates[coordinateIndex - 2], // start x
                                   coordinates[coordinateIndex - 1], // start y
                                   coordinates[coordinateIndex++],   // control point x
                                   coordinates[coordinateIndex++],   // control point y
                                   coordinates[coordinateIndex++],   // end x
                                   coordinates[coordinateIndex++],   // end y
                                   averageScale);
                    #endregion
                    break;
                }
            }

            // finish generation
            polygonList.Finish();
            return(polygonList.RawDatas);
        }
Esempio n. 3
0
        /// <summary>
        /// build arc to beziers
        /// </summary>
        /// <param name="polygonList">polygon List</param>
        /// <param name="centerX">coordinate X of center point</param>
        /// <param name="centerY">coordinate Y of center point</param>
        /// <param name="radiusX">radius X</param>
        /// <param name="radiusY">radius Y</param>
        /// <param name="angle">angle of arc</param>
        /// <param name="startAngle">angle start sweep</param>
        /// <param name="sweepAngle">angle sweep</param>
        /// <param name="scale">scale</param>
        private void BuildBezierArc(RawPolygonList polygonList, double centerX, double centerY, double radiusX, double radiusY, double angle, double startAngle, double sweepAngle, double scale)
        {
            #region variable
            int numberVertices;
            double tempCenterX = centerX;
            double tempCenterY = centerY;
            centerX = centerY = 0.0;
            double[] vertices = new double[26];
            #endregion

            #region recalculate start angle and sweep angle
            startAngle = startAngle % TwoPi;

            if (sweepAngle > TwoPi) sweepAngle = TwoPi;
            else if (sweepAngle < -TwoPi) sweepAngle = -TwoPi;
            #endregion

            #region if sweep angle < 1e -10 then cannot draw arc
            if (Math.Abs(sweepAngle) < 1e-10)
            {
                numberVertices = 4;
                polygonList.LineTo(
                centerX + radiusX * Math.Cos(startAngle),
                centerY + radiusY * Math.Sin(startAngle));
                polygonList.LineTo(
                centerX + radiusX * Math.Cos(startAngle + sweepAngle)
                , centerY + radiusY * Math.Sin(startAngle + sweepAngle));
                return;
            }
            #endregion

            #region calculate all control point in bezier
            double totalSweep = 0.0, localSweep = 0.0;
            double prevSweep;
            numberVertices = 2;
            double x0, y0, tx, ty, sn, cs, tempX;
            bool done = false;

            #region when sweep angle less than 0
            if (sweepAngle > 0)
            {

                do
                {
                    prevSweep = totalSweep;
                    localSweep = SmallStepAngle;
                    totalSweep += localSweep;
                    if (totalSweep >= sweepAngle - 0.01)
                    {
                        localSweep = sweepAngle - prevSweep;
                        done = true;
                    }

                    #region create new control points in beziers

                    x0 = Math.Cos(localSweep / 2.0);
                    y0 = Math.Sin(localSweep / 2.0);
                    tx = (1.0 - x0) * 4.0 / 3.0;
                    ty = y0 - tx * x0 / y0;
                    tempX = x0 + tx;

                    //calculate sin and code of middle angle
                    sn = Math.Sin(startAngle + localSweep / 2.0);
                    cs = Math.Cos(startAngle + localSweep / 2.0);

                    vertices[numberVertices - 2] = radiusX * (x0 * cs + y0 * sn);
                    vertices[numberVertices - 1] = radiusY * (x0 * sn - y0 * cs);
                    vertices[numberVertices] = radiusX * (tempX * cs + ty * sn);
                    vertices[numberVertices + 1] = radiusY * (tempX * sn - ty * cs);
                    vertices[numberVertices + 2] = radiusX * (tempX * cs - ty * sn);
                    vertices[numberVertices + 3] = radiusY * (tempX * sn + ty * cs);
                    vertices[numberVertices + 4] = radiusX * (x0 * cs - y0 * sn);
                    vertices[numberVertices + 5] = radiusY * (x0 * sn + y0 * cs);
                    #endregion

                    numberVertices += 6;
                    startAngle += localSweep;
                }
                while (!done && numberVertices < 26);
            }
            #endregion

            #region when negative sweep angle
            else
            {
                do
                {
                    prevSweep = totalSweep;
                    localSweep = SmallStepAngleNegative;
                    totalSweep += localSweep;
                    if (totalSweep <= sweepAngle + 0.01)
                    {
                        localSweep = sweepAngle - prevSweep;
                        done = true;
                    }

                    #region create new control points in beziers
                    x0 = Math.Cos(localSweep / 2.0);
                    y0 = Math.Sin(localSweep / 2.0);
                    tx = (1.0 - x0) * 4.0 / 3.0;
                    ty = y0 - tx * x0 / y0;
                    tempX = x0 + tx;

                    //calculate sin and code of middle angle
                    sn = Math.Sin(startAngle + localSweep / 2.0);
                    cs = Math.Cos(startAngle + localSweep / 2.0);

                    vertices[numberVertices - 2] = radiusX * (x0 * cs + y0 * sn);
                    vertices[numberVertices - 1] = radiusY * (x0 * sn - y0 * cs);
                    vertices[numberVertices] = radiusX * (tempX * cs + ty * sn);
                    vertices[numberVertices + 1] = radiusY * (tempX * sn - ty * cs);
                    vertices[numberVertices + 2] = radiusX * (tempX * cs - ty * sn);
                    vertices[numberVertices + 3] = radiusY * (tempX * sn + ty * cs);
                    vertices[numberVertices + 4] = radiusX * (x0 * cs - y0 * sn);
                    vertices[numberVertices + 5] = radiusY * (x0 * sn + y0 * cs);
                    #endregion

                    numberVertices += 6;
                    startAngle += localSweep;
                }
                while (!done && numberVertices < 26);
            }
            #endregion

            #endregion

            #region generate points from control points of bezier curves
            double cosAngle = Math.Cos(angle);
            double sinAngle = Math.Sin(angle);

            int i = 0;
            polygonList.MoveTo(vertices[0] * cosAngle - vertices[1] * sinAngle + tempCenterX, vertices[0] * sinAngle + vertices[1] * cosAngle + tempCenterY);
            while (i + 7 < numberVertices)
            {
                BuildCurve(polygonList,
                vertices[i + 0] * cosAngle - vertices[i + 1] * sinAngle + tempCenterX, vertices[i + 0] * sinAngle + vertices[i + 1] * cosAngle + tempCenterY,
                vertices[i + 2] * cosAngle - vertices[i + 3] * sinAngle + tempCenterX, vertices[i + 2] * sinAngle + vertices[i + 3] * cosAngle + tempCenterY,
                vertices[i + 4] * cosAngle - vertices[i + 5] * sinAngle + tempCenterX, vertices[i + 4] * sinAngle + vertices[i + 5] * cosAngle + tempCenterY,
                vertices[i + 6] * cosAngle - vertices[i + 7] * sinAngle + tempCenterX, vertices[i + 6] * sinAngle + vertices[i + 7] * cosAngle + tempCenterY,
                scale);
                i += 6;
            }
            #endregion
        }
Esempio n. 4
0
        /// <summary>
        /// build arc to beziers
        /// </summary>
        /// <param name="polygonList">polygon List</param>
        /// <param name="centerX">coordinate X of center point</param>
        /// <param name="centerY">coordinate Y of center point</param>
        /// <param name="radiusX">radius X</param>
        /// <param name="radiusY">radius Y</param>
        /// <param name="angle">angle of arc</param>
        /// <param name="startAngle">angle start sweep</param>
        /// <param name="sweepAngle">angle sweep</param>
        /// <param name="scale">scale</param>
        private void BuildBezierArc(RawPolygonList polygonList, double centerX, double centerY, double radiusX, double radiusY, double angle, double startAngle, double sweepAngle, double scale)
        {
            #region variable
            int    numberVertices;
            double tempCenterX = centerX;
            double tempCenterY = centerY;
            centerX = centerY = 0.0;
            double[] vertices = new double[26];
            #endregion

            #region recalculate start angle and sweep angle
            startAngle = startAngle % TwoPi;

            if (sweepAngle > TwoPi)
            {
                sweepAngle = TwoPi;
            }
            else if (sweepAngle < -TwoPi)
            {
                sweepAngle = -TwoPi;
            }
            #endregion

            #region if sweep angle < 1e -10 then cannot draw arc
            if (Math.Abs(sweepAngle) < 1e-10)
            {
                numberVertices = 4;
                polygonList.LineTo(
                    centerX + radiusX * Math.Cos(startAngle),
                    centerY + radiusY * Math.Sin(startAngle));
                polygonList.LineTo(
                    centerX + radiusX * Math.Cos(startAngle + sweepAngle)
                    , centerY + radiusY * Math.Sin(startAngle + sweepAngle));
                return;
            }
            #endregion

            #region calculate all control point in bezier
            double totalSweep = 0.0, localSweep = 0.0;
            double prevSweep;
            numberVertices = 2;
            double x0, y0, tx, ty, sn, cs, tempX;
            bool   done = false;

            #region when sweep angle less than 0
            if (sweepAngle > 0)
            {
                do
                {
                    prevSweep   = totalSweep;
                    localSweep  = SmallStepAngle;
                    totalSweep += localSweep;
                    if (totalSweep >= sweepAngle - 0.01)
                    {
                        localSweep = sweepAngle - prevSweep;
                        done       = true;
                    }

                    #region create new control points in beziers

                    x0    = Math.Cos(localSweep / 2.0);
                    y0    = Math.Sin(localSweep / 2.0);
                    tx    = (1.0 - x0) * 4.0 / 3.0;
                    ty    = y0 - tx * x0 / y0;
                    tempX = x0 + tx;

                    //calculate sin and code of middle angle
                    sn = Math.Sin(startAngle + localSweep / 2.0);
                    cs = Math.Cos(startAngle + localSweep / 2.0);

                    vertices[numberVertices - 2] = radiusX * (x0 * cs + y0 * sn);
                    vertices[numberVertices - 1] = radiusY * (x0 * sn - y0 * cs);
                    vertices[numberVertices]     = radiusX * (tempX * cs + ty * sn);
                    vertices[numberVertices + 1] = radiusY * (tempX * sn - ty * cs);
                    vertices[numberVertices + 2] = radiusX * (tempX * cs - ty * sn);
                    vertices[numberVertices + 3] = radiusY * (tempX * sn + ty * cs);
                    vertices[numberVertices + 4] = radiusX * (x0 * cs - y0 * sn);
                    vertices[numberVertices + 5] = radiusY * (x0 * sn + y0 * cs);
                    #endregion

                    numberVertices += 6;
                    startAngle     += localSweep;
                }while (!done && numberVertices < 26);
            }
            #endregion

            #region when negative sweep angle
            else
            {
                do
                {
                    prevSweep   = totalSweep;
                    localSweep  = SmallStepAngleNegative;
                    totalSweep += localSweep;
                    if (totalSweep <= sweepAngle + 0.01)
                    {
                        localSweep = sweepAngle - prevSweep;
                        done       = true;
                    }

                    #region create new control points in beziers
                    x0    = Math.Cos(localSweep / 2.0);
                    y0    = Math.Sin(localSweep / 2.0);
                    tx    = (1.0 - x0) * 4.0 / 3.0;
                    ty    = y0 - tx * x0 / y0;
                    tempX = x0 + tx;

                    //calculate sin and code of middle angle
                    sn = Math.Sin(startAngle + localSweep / 2.0);
                    cs = Math.Cos(startAngle + localSweep / 2.0);

                    vertices[numberVertices - 2] = radiusX * (x0 * cs + y0 * sn);
                    vertices[numberVertices - 1] = radiusY * (x0 * sn - y0 * cs);
                    vertices[numberVertices]     = radiusX * (tempX * cs + ty * sn);
                    vertices[numberVertices + 1] = radiusY * (tempX * sn - ty * cs);
                    vertices[numberVertices + 2] = radiusX * (tempX * cs - ty * sn);
                    vertices[numberVertices + 3] = radiusY * (tempX * sn + ty * cs);
                    vertices[numberVertices + 4] = radiusX * (x0 * cs - y0 * sn);
                    vertices[numberVertices + 5] = radiusY * (x0 * sn + y0 * cs);
                    #endregion

                    numberVertices += 6;
                    startAngle     += localSweep;
                }while (!done && numberVertices < 26);
            }
            #endregion

            #endregion

            #region generate points from control points of bezier curves
            double cosAngle = Math.Cos(angle);
            double sinAngle = Math.Sin(angle);

            int i = 0;
            polygonList.MoveTo(vertices[0] * cosAngle - vertices[1] * sinAngle + tempCenterX, vertices[0] * sinAngle + vertices[1] * cosAngle + tempCenterY);
            while (i + 7 < numberVertices)
            {
                BuildCurve(polygonList,
                           vertices[i + 0] * cosAngle - vertices[i + 1] * sinAngle + tempCenterX, vertices[i + 0] * sinAngle + vertices[i + 1] * cosAngle + tempCenterY,
                           vertices[i + 2] * cosAngle - vertices[i + 3] * sinAngle + tempCenterX, vertices[i + 2] * sinAngle + vertices[i + 3] * cosAngle + tempCenterY,
                           vertices[i + 4] * cosAngle - vertices[i + 5] * sinAngle + tempCenterX, vertices[i + 4] * sinAngle + vertices[i + 5] * cosAngle + tempCenterY,
                           vertices[i + 6] * cosAngle - vertices[i + 7] * sinAngle + tempCenterX, vertices[i + 6] * sinAngle + vertices[i + 7] * cosAngle + tempCenterY,
                           scale);
                i += 6;
            }
            #endregion
        }