Пример #1
0
        //---------------------------------------------------------------------
        public void DrawArc(
            float fromX, float fromY, float endX, float endY,
            float xaxisRotationAngleDec, float rx, float ry,
            SvgArcSize arcSize, SvgArcSweep arcSweep)
        {
            //------------------
            //SVG Elliptical arc ...
            //from Apache Batik
            //-----------------

            CenterFormArc centerFormArc = new CenterFormArc();

            ComputeArc2(fromX, fromY, rx, ry,
                        AggMath.deg2rad(xaxisRotationAngleDec),
                        arcSize == SvgArcSize.Large,
                        arcSweep == SvgArcSweep.Negative,
                        endX, endY, ref centerFormArc);

            //
            using (VectorToolBox.Borrow(out Arc arcTool))
                using (VxsTemp.Borrow(out var v1, out var v2, out var v3))
                {
                    arcTool.Init(centerFormArc.cx, centerFormArc.cy, rx, ry,
                                 centerFormArc.radStartAngle,
                                 (centerFormArc.radStartAngle + centerFormArc.radSweepDiff));
                    bool stopLoop = false;
                    foreach (VertexData vertexData in arcTool.GetVertexIter())
                    {
                        switch (vertexData.command)
                        {
                        case VertexCmd.NoMore:
                            stopLoop = true;
                            break;

                        default:
                            v1.AddVertex(vertexData.x, vertexData.y, vertexData.command);
                            //yield return vertexData;
                            break;
                        }
                        //------------------------------
                        if (stopLoop)
                        {
                            break;
                        }
                    }

                    double scaleRatio = 1;
                    if (centerFormArc.scaleUp)
                    {
                        int vxs_count = v1.Count;
                        v1.GetVertex(0, out double px0, out double py0);
                        v1.GetVertex(vxs_count - 1, out double px_last, out double py_last);
                        double distance1 = Math.Sqrt((px_last - px0) * (px_last - px0) + (py_last - py0) * (py_last - py0));
                        double distance2 = Math.Sqrt((endX - fromX) * (endX - fromX) + (endY - fromY) * (endY - fromY));
                        if (distance1 < distance2)
                        {
                            scaleRatio = distance2 / distance1;
                        }
                        else
                        {
                        }
                    }

                    if (xaxisRotationAngleDec != 0)
                    {
                        //also  rotate
                        if (centerFormArc.scaleUp)
                        {
                            //var mat = Affine.NewMatix(
                            //        new AffinePlan(AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy),
                            //        new AffinePlan(AffineMatrixCommand.Scale, scaleRatio, scaleRatio),
                            //        new AffinePlan(AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)),
                            //        new AffinePlan(AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy));
                            //mat1.TransformToVxs(v1, v2);
                            //v1 = v2;

                            AffineMat mat = AffineMat.Iden();
                            mat.Translate(-centerFormArc.cx, -centerFormArc.cy);
                            mat.Scale(scaleRatio);
                            mat.RotateDeg(xaxisRotationAngleDec);
                            mat.Translate(centerFormArc.cx, centerFormArc.cy);
                            VertexStoreTransformExtensions.TransformToVxs(mat, v1, v2);
                            v1 = v2;
                        }
                        else
                        {
                            //not scale
                            //var mat = Affine.NewMatix(
                            //        AffinePlan.Translate(-centerFormArc.cx, -centerFormArc.cy),
                            //        AffinePlan.RotateDeg(xaxisRotationAngleDec),
                            //        AffinePlan.Translate(centerFormArc.cx, centerFormArc.cy));
                            //mat.TransformToVxs(v1, v2);
                            //v1 = v2;

                            AffineMat mat = AffineMat.Iden();
                            mat.Translate(-centerFormArc.cx, -centerFormArc.cy);
                            mat.RotateDeg(xaxisRotationAngleDec);
                            mat.Translate(centerFormArc.cx, centerFormArc.cy);
                            VertexStoreTransformExtensions.TransformToVxs(mat, v1, v2);
                            v1 = v2;
                        }
                    }
                    else
                    {
                        //no rotate
                        if (centerFormArc.scaleUp)
                        {
                            //var mat = Affine.NewMatix(
                            //        new AffinePlan(AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy),
                            //        new AffinePlan(AffineMatrixCommand.Scale, scaleRatio, scaleRatio),
                            //        new AffinePlan(AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy));

                            //mat.TransformToVxs(v1, v2);
                            //v1 = v2;
                            AffineMat mat = AffineMat.Iden();
                            mat.Translate(-centerFormArc.cx, -centerFormArc.cy);
                            mat.RotateDeg(scaleRatio);
                            mat.Translate(centerFormArc.cx, centerFormArc.cy);
                            //
                            VertexStoreTransformExtensions.TransformToVxs(mat, v1, v2);
                            v1 = v2;
                        }
                    }

                    //_stroke.Width = this.StrokeWidth;
                    //_stroke.MakeVxs(v1, v3);
                    //_pcx.DrawGfxPath(_pcx.StrokeColor, _pathRenderVxBuilder.CreatePathRenderVx(v3));
                }
        }
Пример #2
0
        //--------------------------------------------------------------------
        public void init(double x0, double y0,
                         double rx, double ry,
                         double angle,
                         bool large_arc_flag,
                         bool sweep_flag,
                         double x2, double y2)
        {
            m_radii_ok = true;

            if (rx < 0.0)
            {
                rx = -rx;
            }
            if (ry < 0.0)
            {
                ry = -rx;
            }

            // Calculate the middle point between
            // the current and the final points
            //------------------------
            double dx2 = (x0 - x2) / 2.0;
            double dy2 = (y0 - y2) / 2.0;

            double cos_a = Math.Cos(angle);
            double sin_a = Math.Sin(angle);

            // Calculate (x1, y1)
            //------------------------
            double x1 = cos_a * dx2 + sin_a * dy2;
            double y1 = -sin_a * dx2 + cos_a * dy2;

            // Ensure radii are large enough
            //------------------------
            double prx = rx * rx;
            double pry = ry * ry;
            double px1 = x1 * x1;
            double py1 = y1 * y1;

            // Check that radii are large enough
            //------------------------
            double radii_check = px1 / prx + py1 / pry;

            if (radii_check > 1.0)
            {
                rx  = Math.Sqrt(radii_check) * rx;
                ry  = Math.Sqrt(radii_check) * ry;
                prx = rx * rx;
                pry = ry * ry;
                if (radii_check > 10.0)
                {
                    m_radii_ok = false;
                }
            }

            // Calculate (cx1, cy1)
            //------------------------
            double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0;
            double sq   = (prx * pry - prx * py1 - pry * px1) / (prx * py1 + pry * px1);
            double coef = sign * Math.Sqrt((sq < 0) ? 0 : sq);
            double cx1  = coef * ((rx * y1) / ry);
            double cy1  = coef * -((ry * x1) / rx);

            //
            // Calculate (cx, cy) from (cx1, cy1)
            //------------------------
            double sx2 = (x0 + x2) / 2.0;
            double sy2 = (y0 + y2) / 2.0;
            double cx  = sx2 + (cos_a * cx1 - sin_a * cy1);
            double cy  = sy2 + (sin_a * cx1 + cos_a * cy1);

            // Calculate the start_angle (angle1) and the sweep_angle (dangle)
            //------------------------
            double ux = (x1 - cx1) / rx;
            double uy = (y1 - cy1) / ry;
            double vx = (-x1 - cx1) / rx;
            double vy = (-y1 - cy1) / ry;
            double p, n;

            // Calculate the angle start
            //------------------------
            n    = Math.Sqrt(ux * ux + uy * uy);
            p    = ux; // (1 * ux) + (0 * uy)
            sign = (uy < 0) ? -1.0 : 1.0;
            double v = p / n;

            if (v < -1.0)
            {
                v = -1.0;
            }
            if (v > 1.0)
            {
                v = 1.0;
            }
            double start_angle = sign * Math.Acos(v);

            // Calculate the sweep angle
            //------------------------
            n    = Math.Sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
            p    = ux * vx + uy * vy;
            sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0;
            v    = p / n;
            if (v < -1.0)
            {
                v = -1.0;
            }
            if (v > 1.0)
            {
                v = 1.0;
            }
            double sweep_angle = sign * Math.Acos(v);

            if (!sweep_flag && sweep_angle > 0)
            {
                sweep_angle -= Math.PI * 2.0;
            }
            else
            if (sweep_flag && sweep_angle < 0)
            {
                sweep_angle += Math.PI * 2.0;
            }

            // We can now build and transform the resulting arc
            //------------------------
            m_arc.init(0.0, 0.0, rx, ry, start_angle, sweep_angle);

            AffineMat mtx = AffineMat.Iden();

            mtx.Rotate(angle);
            mtx.Translate(cx, cy);

            //Affine mtx = Affine.New(
            //    AffinePlan.Rotate(angle),
            //    AffinePlan.Translate(cx, cy)
            //    );

            for (int i = 2; i < m_arc.m_num_vertices - 2; i += 2)
            {
                mtx.Transform(ref m_arc.m_vertices[i], ref m_arc.m_vertices[i + 1]);
            }

            // We must make sure that the starting and ending points
            // exactly coincide with the initial (x0,y0) and (x2,y2)
            m_arc.m_vertices[0] = x0;
            m_arc.m_vertices[1] = y0;
            if (m_arc.m_num_vertices > 2)
            {
                m_arc.m_vertices[m_arc.m_num_vertices - 2] = x2;
                m_arc.m_vertices[m_arc.m_num_vertices - 1] = y2;
            }
        }