Пример #1
0
        static void FlattenPoints(EdgeSegment segment, List <Vec2Info> points)
        {
            switch (segment.SegmentKind)
            {
            default: throw new NotSupportedException();

            case EdgeSegmentKind.LineSegment:
            {
                LinearSegment seg = (LinearSegment)segment;
                points.Add(new Vec2Info(segment, Vec2PointKind.Touch1, seg.P0));
            }
            break;

            case EdgeSegmentKind.QuadraticSegment:
            {
                QuadraticSegment seg = (QuadraticSegment)segment;
                points.Add(new Vec2Info(segment, Vec2PointKind.Touch1, seg.P0));
                points.Add(new Vec2Info(segment, Vec2PointKind.C2, seg.P1));
            }
            break;

            case EdgeSegmentKind.CubicSegment:
            {
                CubicSegment seg = (CubicSegment)segment;
                points.Add(new Vec2Info(segment, Vec2PointKind.Touch1, seg.P0));
                points.Add(new Vec2Info(segment, Vec2PointKind.C3, seg.P1));
                points.Add(new Vec2Info(segment, Vec2PointKind.C3, seg.P2));
            }
            break;
            }
        }
Пример #2
0
 public override void splitInThirds(out EdgeSegment part1, out EdgeSegment part2, out EdgeSegment part3)
 {
     part1 = new CubicSegment(p[0], Vector2.IsEq(p[0], p[1]) ? p[0] : mix(p[0], p[1], 1 / 3.0), mix(mix(p[0], p[1], 1 / 3.0), mix(p[1], p[2], 1 / 3.0), 1 / 3.0), point(1 / 3.0), color);
     part2 = new CubicSegment(point(1 / 3.0),
                              mix(mix(mix(p[0], p[1], 1 / 3.0), mix(p[1], p[2], 1 / 3.0), 1 / 3.0), mix(mix(p[1], p[2], 1 / 3.0), mix(p[2], p[3], 1 / 3.0), 1 / 3.0), 2 / 3.0),
                              mix(mix(mix(p[0], p[1], 2 / 3.0), mix(p[1], p[2], 2 / 3.0), 2 / 3.0), mix(mix(p[1], p[2], 2 / 3.0), mix(p[2], p[3], 2 / 3.0), 2 / 3.0), 1 / 3.0),
                              point(2 / 3.0), color);
     part3 = new CubicSegment(point(2 / 3.0), mix(mix(p[1], p[2], 2 / 3.0), mix(p[2], p[3], 2 / 3.0), 2 / 3.0), Vector2.IsEq(p[2], p[3]) ? p[3] : mix(p[2], p[3], 2 / 3.0), p[3], color);
 }
Пример #3
0
 public override void splitInThirds(out EdgeSegment part1, out EdgeSegment part2, out EdgeSegment part3)
 {
     part1 = new CubicSegment(_p0, Vector2.IsEq(_p0, _p1) ? _p0 : mix(_p0, _p1, 1 / 3.0), mix(mix(_p0, _p1, 1 / 3.0), mix(_p1, _p2, 1 / 3.0), 1 / 3.0), point(1 / 3.0), color);
     part2 = new CubicSegment(point(1 / 3.0),
                              mix(mix(mix(_p0, _p1, 1 / 3.0), mix(_p1, _p2, 1 / 3.0), 1 / 3.0), mix(mix(_p1, _p2, 1 / 3.0), mix(_p2, _p3, 1 / 3.0), 1 / 3.0), 2 / 3.0),
                              mix(mix(mix(_p0, _p1, 2 / 3.0), mix(_p1, _p2, 2 / 3.0), 2 / 3.0), mix(mix(_p1, _p2, 2 / 3.0), mix(_p2, _p3, 2 / 3.0), 2 / 3.0), 1 / 3.0),
                              point(2 / 3.0), color);
     part3 = new CubicSegment(point(2 / 3.0), mix(mix(_p1, _p2, 2 / 3.0), mix(_p2, _p3, 2 / 3.0), 2 / 3.0), Vector2.IsEq(_p2, _p3) ? _p3 : mix(_p2, _p3, 2 / 3.0), _p3, color);
 }
Пример #4
0
 public override void SplitInThirds(out EdgeSegment part1, out EdgeSegment part2, out EdgeSegment part3)
 {
     part1 = new CubicSegment(Color, _p[0], _p[0] == _p[1] ? _p[0] : Arithmetic.Mix(_p[0], _p[1], 1.0 / 3.0),
                              Arithmetic.Mix(Arithmetic.Mix(_p[0], _p[1], 1.0 / 3.0), Arithmetic.Mix(_p[1], _p[2], 1.0 / 3.0),
                                             1.0 / 3.0), Point(1.0 / 3.0));
     part2 = new CubicSegment(Color, Point(1.0 / 3.0),
                              Arithmetic.Mix(
                                  Arithmetic.Mix(Arithmetic.Mix(_p[0], _p[1], 1.0 / 3.0), Arithmetic.Mix(_p[1], _p[2], 1.0 / 3.0),
                                                 1.0 / 3.0),
                                  Arithmetic.Mix(Arithmetic.Mix(_p[1], _p[2], 1.0 / 3.0), Arithmetic.Mix(_p[2], _p[3], 1.0 / 3.0),
                                                 1.0 / 3.0), 2.0 / 3.0),
                              Arithmetic.Mix(
                                  Arithmetic.Mix(Arithmetic.Mix(_p[0], _p[1], 2.0 / 3.0), Arithmetic.Mix(_p[1], _p[2], 2.0 / 3.0),
                                                 2.0 / 3.0),
                                  Arithmetic.Mix(Arithmetic.Mix(_p[1], _p[2], 2.0 / 3.0), Arithmetic.Mix(_p[2], _p[3], 2.0 / 3.0),
                                                 2.0 / 3.0), 1.0 / 3.0),
                              Point(2.0 / 3.0));
     part3 = new CubicSegment(Color, Point(2.0 / 3.0),
                              Arithmetic.Mix(Arithmetic.Mix(_p[1], _p[2], 2.0 / 3.0), Arithmetic.Mix(_p[2], _p[3], 2.0 / 3.0),
                                             2.0 / 3.0),
                              _p[2] == _p[3] ? _p[3] : Arithmetic.Mix(_p[2], _p[3], 2.0 / 3.0), _p[3]);
 }
Пример #5
0
        static Vertex2d ConvToV2d(PointD p) => new Vertex2d(p.X, p.Y); //temp

        /// <summary>
        /// fill inner and outer border from corner0 to corner1
        /// </summary>
        /// <param name="painter"></param>
        /// <param name="c0"></param>
        /// <param name="c1"></param>
        void FillBorders(AggPainter painter, ContourCorner c0, ContourCorner c1)
        {
            //counter-clockwise

            if (!c0.MiddlePoint_IsTouchPoint)
            {
                return;
            }

            //with a given corner, have have information of 3 points
            //left-point of the corner,=> from vertex
            //middle-point, current vertex
            //right-point,=> next vertex
            //a vertex may be touch-curve vertext, or 'not-touch-curve' vertex

            //'is not touch-curve point', => this vertex is a  control point of C3 or C4 curve,
            //-------------------------------------------------------

            if (c0.RightPoint_IsTouchPoint)
            {
                //c0 => touch curve
                //c1 => touch curve,
                //we create an imaginary line from  c0 to c1
                //then we create an 'inner border' of a line from c0 to c1
                //and we create an 'outer border' of a line from c0 to c1
                //
                using (Tools.BorrowVxs(out var v1))
                {
                    //1. inner-border, set fill mode to inform proper color encoding of inner border
                    _msdfEdgePxBlender.FillMode = MsdfEdgePixelBlender.BlenderFillMode.InnerBorder;



                    //2020-03-13, version 3 fill is still better than v3.1,
                    //TODO: review version v3.1


                    if (_use_v3_1)
                    {
                        //version 3.1 fill technique
                        CreateBorder(v1, ConvToV2d(c1.RightPoint), ConvToV2d(c1.MiddlePoint), ConvToV2d(c0.MiddlePoint), ConvToV2d(c0.LeftPoint));
                    }
                    else
                    {
                        //version 3 fill technique
                        CreateInnerBorder(v1,
                                          c0.MiddlePoint.X, c0.MiddlePoint.Y,
                                          c1.MiddlePoint.X, c1.MiddlePoint.Y, INNER_BORDER_W);
                    }

                    painter.Fill(v1, c0.InnerColor);
                    //-------------
                    v1.Clear(); //reuse
                                //2. outer-border, set fill mode too.


                    _msdfEdgePxBlender.FillMode = MsdfEdgePixelBlender.BlenderFillMode.OuterBorder;

                    if (_use_v3_1)
                    {
                        //version 3.1 fill technique
                        CreateBorder(v1, ConvToV2d(c0.LeftPoint), ConvToV2d(c0.MiddlePoint), ConvToV2d(c1.MiddlePoint), ConvToV2d(c1.RightPoint));
                    }
                    else
                    {
                        //version 3 fill technique
                        CreateOuterBorder(v1,
                                          c0.MiddlePoint.X, c0.MiddlePoint.Y,
                                          c1.MiddlePoint.X, c1.MiddlePoint.Y, OUTER_BORDER_W);
                    }


                    painter.Fill(v1, c0.OuterColor);
                }
            }
            else
            {
                //painter.CurrentBxtBlendOp = null;

                //**
                //c0 is touch line,
                //but c1 is not, this means=> next segment will be a curve(C3 or C4 curve)
                //
                EdgeSegment ownerSeg = c1.CenterSegment;

                switch (ownerSeg.SegmentKind)
                {
                default: throw new NotSupportedException();

                case EdgeSegmentKind.CubicSegment:
                {
                    //approximate
                    CubicSegment cs = (CubicSegment)ownerSeg;
                    using (Tools.BorrowVxs(out var v1))
                        using (Tools.BorrowShapeBuilder(out var b))
                            using (Tools.BorrowStroke(out var strk))
                            {
                                b.MoveTo(cs.P0.x + _dx, cs.P0.y + _dy) //...
                                .Curve4To(cs.P1.x + _dx, cs.P1.y + _dy,
                                          cs.P2.x + _dx, cs.P2.y + _dy,
                                          cs.P3.x + _dx, cs.P3.y + _dy)
                                .NoMore()
                                .Flatten();


                                //-----------------------
                                //fill outside part of the curve
                                strk.Width = CURVE_STROKE_EACHSIDE * 2;
                                strk.StrokeSideForOpenShape = StrokeSideForOpenShape.Outside;
                                strk.MakeVxs(b.CurrentSharedVxs, v1);

                                painter.Fill(v1, c0.OuterColor);
                                //-----------------------
                                //fill inside part of the curve
                                v1.Clear(); //reuse
                                strk.StrokeSideForOpenShape = StrokeSideForOpenShape.Inside;
                                strk.MakeVxs(b.CurrentSharedVxs, v1);
                                painter.Fill(v1, c0.InnerColor);
                                //-----------------------
                            }
                }
                break;

                case EdgeSegmentKind.QuadraticSegment:
                {
                    QuadraticSegment qs = (QuadraticSegment)ownerSeg;

                    using (Tools.BorrowVxs(out var v1))
                        using (Tools.BorrowShapeBuilder(out var b))
                            using (Tools.BorrowStroke(out var strk))
                            {
                                b.MoveTo(qs.P0.x + _dx, qs.P0.y + _dy)//...
                                .Curve3To(qs.P1.x + _dx, qs.P1.y + _dy,
                                          qs.P2.x + _dx, qs.P2.y + _dy)
                                .NoMore()
                                .Flatten();

                                //-----------------------
                                //fill outside part of the curve
                                strk.Width = CURVE_STROKE_EACHSIDE * 2;
                                strk.StrokeSideForOpenShape = StrokeSideForOpenShape.Outside;
                                strk.MakeVxs(b.CurrentSharedVxs, v1);
                                painter.Fill(v1, c0.OuterColor);
                                //-----------------------
                                //fill inside part of the curve
                                v1.Clear();//reuse
                                strk.StrokeSideForOpenShape = StrokeSideForOpenShape.Inside;
                                strk.MakeVxs(b.CurrentSharedVxs, v1);
                                painter.Fill(v1, c0.InnerColor);
                                //-----------------------
                            }
                }
                break;
                }
            }
        }