示例#1
0
        void BuildEndCap(
            double x0, double y0,
            double x1, double y1,
            List <Vector> outputVectors)
        {
            switch (LineCapStyle)
            {
            default: throw new NotSupportedException();

            case LineCap.Butt:
                break;

            case LineCap.Square:
                break;

            case LineCap.Round:
            {
                //------------------------
                //x0,y0 -> end of line 1
                //x1,y1 -> end of line 2
                //------------------------
                double  c_x   = (x0 + x1) / 2;
                double  c_y   = (y0 + y1) / 2;
                Vector2 delta = new Vector2(x1 - c_x, y1 - c_y);
                ArcGenerator.GenerateArcNew(outputVectors,
                                            c_x, c_y, delta, AggMath.deg2rad(180));
            }
            break;
            }
        }
示例#2
0
 public void SetFilterOffset(double dx, double dy)
 {
     m_dx_dbl = dx;
     m_dy_dbl = dy;
     m_dx_int = AggMath.iround(dx * img_subpix_const.SCALE);
     m_dy_int = AggMath.iround(dy * img_subpix_const.SCALE);
 }
示例#3
0
 //bool AutoClose
 //{
 //    get { return m_auto_close; }
 //    set { this.m_auto_close = value; }
 //}
 //--------------------------------------------------------------------
 public void ResetGamma(IGammaFunction gamma_function)
 {
     for (int i = AA_SCALE - 1; i >= 0; --i)
     {
         m_gammaLut[i] = (int)AggMath.uround(
             gamma_function.GetGamma((float)(i) / AA_MASK) * AA_MASK);
     }
 }
示例#4
0
        void SetGamma(float g)
        {
            m_gamma = g;
            float inv_g = (float)(1.0 / g);

            for (int i = GAMMA_SIZE - 1; i >= 0; --i)
            {
                m_dir_gamma[i] = (byte)AggMath.uround(Math.Pow(i / (float)GAMMA_MASK, m_gamma) * (float)GAMMA_MASK);
                m_inv_gamma[i] = (byte)AggMath.uround(Math.Pow(i / (float)GAMMA_MASK, inv_g) * (float)GAMMA_MASK);
            }
        }
        //--------------------------------------------------------------------
        public void Prepare()
        {
            CoordAndColor c0, c1, c2;

            base.LoadArrangedVertices(out c0, out c1, out c2);
            m_y2   = (int)c1.y;
            m_swap = AggMath.Cross(c0.x, c0.y,
                                   c2.x, c2.y,
                                   c1.x, c1.y) < 0.0;
            m_rgba1.Init(c0, c2);
            m_rgba2.Init(c0, c1);
            m_rgba3.Init(c1, c2);
        }
示例#6
0
 public bool IsEqual(Vertex2d val)
 {
     return(AggMath.calc_distance(x, y, val.x, val.y) <= AggMath.VERTEX_DISTANCE_EPSILON);
     //if ((dist = AggMath.calc_distance(x, y, val.x, val.y)) > AggMath.VERTEX_DISTANCE_EPSILON)
     //{
     //    //diff enough=> this is NOT equal with val
     //    return false;
     //}
     //else
     //{
     //    //not diff enough => this is equal (with val)
     //    dist = 1.0 / AggMath.VERTEX_DISTANCE_EPSILON;
     //    return true;
     //}
 }
示例#7
0
 //--------------------------------------------------------------------
 public SpanGenGradient(ISpanInterpolator inter,
                        IGradientValueCalculator gvc,
                        IGradientColorsProvider m_colorsProvider,
                        double d1, double d2)
 {
     this.m_interpolator      = inter;
     this.m_grValueCalculator = gvc;
     this.m_colorsProvider    = m_colorsProvider;
     m_d1 = AggMath.iround(d1 * GR_SUBPIX_SCALE);
     m_d2 = AggMath.iround(d2 * GR_SUBPIX_SCALE);
     dd   = m_d2 - m_d1;
     if (dd < 1)
     {
         dd = 1;
     }
     stepRatio = (float)m_colorsProvider.GradientSteps / (float)dd;
 }
示例#8
0
        //helper class for generate arc
        //
        public static void GenerateArcNew(List <Vector> output, double cx,
                                          double cy,
                                          Vector2 startDelta,
                                          double sweepAngleRad)
        {
            //TODO: review here ***
            int    nsteps   = 4;
            double eachStep = AggMath.rad2deg(sweepAngleRad) / nsteps;
            double angle    = 0;

            for (int i = 0; i < nsteps; ++i)
            {
                Vector2 newPerpend = startDelta.RotateInDegree(angle);
                Vector2 newpos     = new Vector2(cx + newPerpend.x, cy + newPerpend.y);
                output.Add(new Vector(newpos.x, newpos.y));
                angle += eachStep;
            }
        }
            public void Calculate(double y)
            {
                double k = (y - m_y1) * m_1dy;

                if (k < 0.0)
                {
                    k = 0.0;
                }
                if (k > 1.0)
                {
                    k = 1.0;
                }
                m_r = m_r1 + AggMath.iround(m_dr * k);
                m_g = m_g1 + AggMath.iround(m_dg * k);
                m_b = m_b1 + AggMath.iround(m_db * k);
                m_a = m_a1 + AggMath.iround(m_da * k);
                m_x = AggMath.iround((m_x1 + m_dx * k) * (double)SUBPIXEL_SCALE);
            }
示例#10
0
        //--------------------------------------------------------------------
        // Sets the triangle and dilates it if needed.
        // The trick here is to calculate beveled joins in the vertices of the
        // triangle and render it as a 6-vertex polygon.
        // It's necessary to achieve numerical stability.
        // However, the coordinates to interpolate colors are calculated
        // as miter joins (calc_intersection).
        public void SetTriangle(double x1, double y1,
                                double x2, double y2,
                                double x3, double y3,
                                double d)
        {
            m_coord_0.x = m_x[0] = x1;
            m_coord_0.y = m_y[0] = y1;
            m_coord_1.x = m_x[1] = x2;
            m_coord_1.y = m_y[1] = y2;
            m_coord_2.x = m_x[2] = x3;
            m_coord_2.y = m_y[2] = y3;
            m_cmd[0]    = VertexCmd.MoveTo;
            m_cmd[1]    = VertexCmd.LineTo;
            m_cmd[2]    = VertexCmd.LineTo;
            m_cmd[3]    = VertexCmd.Stop;

            if (d != 0.0)
            {
                AggMath.DilateTriangle(m_coord_0.x, m_coord_0.y,
                                       m_coord_1.x, m_coord_1.y,
                                       m_coord_2.x, m_coord_2.y,
                                       m_x, m_y, d);

                AggMath.CalcIntersect(m_x[4], m_y[4], m_x[5], m_y[5],
                                      m_x[0], m_y[0], m_x[1], m_y[1],
                                      out m_coord_0.x, out m_coord_0.y);

                AggMath.CalcIntersect(m_x[0], m_y[0], m_x[1], m_y[1],
                                      m_x[2], m_y[2], m_x[3], m_y[3],
                                      out m_coord_1.x, out m_coord_1.y);

                AggMath.CalcIntersect(m_x[2], m_y[2], m_x[3], m_y[3],
                                      m_x[4], m_y[4], m_x[5], m_y[5],
                                      out m_coord_2.x, out m_coord_2.y);

                m_cmd[3] = VertexCmd.LineTo;
                m_cmd[4] = VertexCmd.LineTo;
                m_cmd[5] = VertexCmd.LineTo;
                m_cmd[6] = VertexCmd.Stop;
            }
        }
示例#11
0
        void CreateMiter(VertexStore output,
                         VertexDistance v0,
                         VertexDistance v1,
                         VertexDistance v2,
                         double dx1, double dy1,
                         double dx2, double dy2,
                         LineJoin lj,
                         double mlimit,
                         double dbevel)
        {
            double xi  = v1.x;
            double yi  = v1.y;
            double di  = 1;
            double lim = m_width_abs * mlimit;
            bool   miter_limit_exceeded = true; // Assume the worst
            bool   intersection_failed  = true; // Assume the worst

            if (AggMath.CalcIntersect(v0.x + dx1, v0.y - dy1,
                                      v1.x + dx1, v1.y - dy1,
                                      v1.x + dx2, v1.y - dy2,
                                      v2.x + dx2, v2.y - dy2,
                                      out xi, out yi))
            {
                // Calculation of the intersection succeeded
                //---------------------
                di = AggMath.calc_distance(v1.x, v1.y, xi, yi);
                if (di <= lim)
                {
                    // Inside the miter limit
                    //---------------------
                    AddVertex(output, xi, yi);
                    miter_limit_exceeded = false;
                }
                intersection_failed = false;
            }
            else
            {
                // Calculation of the intersection failed, most probably
                // the three points lie one straight line.
                // First check if v0 and v2 lie on the opposite sides of vector:
                // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
                // to the line determined by vertices v0 and v1.
                // This condition determines whether the next line segments continues
                // the previous one or goes back.
                //----------------
                double x2 = v1.x + dx1;
                double y2 = v1.y - dy1;
                if ((AggMath.Cross(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
                    (AggMath.Cross(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
                {
                    // This case means that the next segment continues
                    // the previous one (straight line)
                    //-----------------
                    AddVertex(output, v1.x + dx1, v1.y - dy1);
                    miter_limit_exceeded = false;
                }
            }

            if (miter_limit_exceeded)
            {
                // Miter limit exceeded
                //------------------------
                switch (lj)
                {
                case LineJoin.MiterRevert:
                    // For the compatibility with SVG, PDF, etc,
                    // we use a simple bevel join instead of
                    // "smart" bevel
                    //-------------------
                    AddVertex(output, v1.x + dx1, v1.y - dy1);
                    AddVertex(output, v1.x + dx2, v1.y - dy2);
                    break;

                case LineJoin.MiterRound:
                    CreateArc(output, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
                    break;

                default:
                    // If no miter-revert, calculate new dx1, dy1, dx2, dy2
                    //----------------
                    if (intersection_failed)
                    {
                        mlimit *= m_width_sign;
                        AddVertex(output, v1.x + dx1 + dy1 * mlimit,
                                  v1.y - dy1 + dx1 * mlimit);
                        AddVertex(output, v1.x + dx2 - dy2 * mlimit,
                                  v1.y - dy2 - dx2 * mlimit);
                    }
                    else
                    {
                        double x1 = v1.x + dx1;
                        double y1 = v1.y - dy1;
                        double x2 = v1.x + dx2;
                        double y2 = v1.y - dy2;
                        di = (lim - dbevel) / (di - dbevel);
                        AddVertex(output, x1 + (xi - x1) * di,
                                  y1 + (yi - y1) * di);
                        AddVertex(output, x2 + (xi - x2) * di,
                                  y2 + (yi - y2) * di);
                    }
                    break;
                }
            }
        }
示例#12
0
        public void CreateJoin(VertexStore output,
                               VertexDistance v0,
                               VertexDistance v1,
                               VertexDistance v2,
                               double len1,
                               double len2)
        {
            double dx1 = m_width * (v1.y - v0.y) / len1;
            double dy1 = m_width * (v1.x - v0.x) / len1;
            double dx2 = m_width * (v2.y - v1.y) / len2;
            double dy2 = m_width * (v2.x - v1.x) / len2;

            output.Clear();
            double cp = AggMath.Cross(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);

            if (cp != 0 && (cp > 0) == (m_width > 0))
            {
                // Inner join
                //---------------
                double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
                if (limit < m_inner_miter_limit)
                {
                    limit = m_inner_miter_limit;
                }

                switch (m_inner_join)
                {
                default:     // inner_bevel
                    AddVertex(output, v1.x + dx1, v1.y - dy1);
                    AddVertex(output, v1.x + dx2, v1.y - dy2);
                    break;

                case InnerJoin.Miter:
                    CreateMiter(output,
                                v0, v1, v2, dx1, dy1, dx2, dy2,
                                LineJoin.MiterRevert,
                                limit, 0);
                    break;

                case InnerJoin.Jag:
                case InnerJoin.Round:
                    cp = (dx1 - dx2) * (dx1 - dx2) + (dy1 - dy2) * (dy1 - dy2);
                    if (cp < len1 * len1 && cp < len2 * len2)
                    {
                        CreateMiter(output,
                                    v0, v1, v2, dx1, dy1, dx2, dy2,
                                    LineJoin.MiterRevert,
                                    limit, 0);
                    }
                    else
                    {
                        if (m_inner_join == InnerJoin.Jag)
                        {
                            AddVertex(output, v1.x + dx1, v1.y - dy1);
                            AddVertex(output, v1.x, v1.y);
                            AddVertex(output, v1.x + dx2, v1.y - dy2);
                        }
                        else
                        {
                            AddVertex(output, v1.x + dx1, v1.y - dy1);
                            AddVertex(output, v1.x, v1.y);
                            CreateArc(output, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
                            AddVertex(output, v1.x, v1.y);
                            AddVertex(output, v1.x + dx2, v1.y - dy2);
                        }
                    }
                    break;
                }
            }
            else
            {
                // Outer join
                //---------------

                // Calculate the distance between v1 and
                // the central point of the bevel line segment
                //---------------
                double dx     = (dx1 + dx2) / 2;
                double dy     = (dy1 + dy2) / 2;
                double dbevel = Math.Sqrt(dx * dx + dy * dy);
                if (m_line_join == LineJoin.Round || m_line_join == LineJoin.Bevel)
                {
                    // This is an optimization that reduces the number of points
                    // in cases of almost collinear segments. If there's no
                    // visible difference between bevel and miter joins we'd rather
                    // use miter join because it adds only one point instead of two.
                    //
                    // Here we calculate the middle point between the bevel points
                    // and then, the distance between v1 and this middle point.
                    // At outer joins this distance always less than stroke width,
                    // because it's actually the height of an isosceles triangle of
                    // v1 and its two bevel points. If the difference between this
                    // width and this value is small (no visible bevel) we can
                    // add just one point.
                    //
                    // The constant in the expression makes the result approximately
                    // the same as in round joins and caps. You can safely comment
                    // out this entire "if".
                    //-------------------
                    if (m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
                    {
                        if (AggMath.CalcIntersect(v0.x + dx1, v0.y - dy1,
                                                  v1.x + dx1, v1.y - dy1,
                                                  v1.x + dx2, v1.y - dy2,
                                                  v2.x + dx2, v2.y - dy2,
                                                  out dx, out dy))
                        {
                            AddVertex(output, dx, dy);
                        }
                        else
                        {
                            AddVertex(output, v1.x + dx1, v1.y - dy1);
                        }
                        return;
                    }
                }

                switch (m_line_join)
                {
                case LineJoin.Miter:
                case LineJoin.MiterRevert:
                case LineJoin.MiterRound:
                    CreateMiter(output,
                                v0, v1, v2, dx1, dy1, dx2, dy2,
                                m_line_join,
                                m_miter_limit,
                                dbevel);
                    break;

                case LineJoin.Round:
                    CreateArc(output, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
                    break;

                default:     // Bevel join
                    AddVertex(output, v1.x + dx1, v1.y - dy1);
                    AddVertex(output, v1.x + dx2, v1.y - dy2);
                    break;
                }
            }
        }
示例#13
0
 public double CalLen(Vertex2d another)
 {
     return(AggMath.calc_distance(x, y, another.x, another.y));
 }
示例#14
0
 //---------------------------------
 //from vector clipper
 static int upscale(double v)
 {
     return(AggMath.iround(v * poly_subpix.SCALE));
 }