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;
            }
        }
        public void BuildJointVertex(
            List <Vector> positiveSideVectors,
            List <Vector> negativeSideVectors)
        {
            if (LineJoinKind == LineJoin.Bevel)
            {
                return;
            }

            //--------------------------------------------------------------
            Vector2 v0v1 = new Vector2(x1 - x0, y1 - y0);
            Vector2 v1v2 = new Vector2(x2 - x1, y2 - y1);

            Vector2 delta_v0v1 = v0v1.RotateInDegree(90).NewLength(HalfWidth);
            Vector2 delta_v1v2 = v1v2.RotateInDegree(90).NewLength(HalfWidth);


            double rad_v0v1       = Math.Atan2(v0v1.y, v0v1.x);
            double rad_v1v2       = Math.Atan2(v1v2.y, v1v2.x);
            double angle_rad_diff = rad_v1v2 - rad_v0v1;

            if (positiveSideVectors != null)
            {
                Vector2 vec_a = new Vector2(x0 + delta_v0v1.x, y0 + delta_v0v1.y);
                Vector2 vec_b = new Vector2(x1 + delta_v0v1.x, y1 + delta_v0v1.y);
                Vector2 vec_c = new Vector2(x1 + delta_v1v2.x, y1 + delta_v1v2.y);
                Vector2 vec_d = new Vector2(x2 + delta_v1v2.x, y2 + delta_v1v2.y);


                Vector2 cutPoint;
                if (MyMath.FindCutPoint(
                        vec_a, vec_b, //a->b
                        vec_c, vec_d, //b->c
                        out cutPoint))
                {
                    if (angle_rad_diff > 0)
                    {
                        //'ACUTE' angle side, 'INNER' join
                        //------------
                        //inner join
                        //v0v1 => v1v2 is inner angle for positive side
                        //and is outter angle of negative side
                        //inside joint share the same cutpoint
                        positiveSideVectors.Add(new Vector(cutPoint.x, cutPoint.y));
                    }
                    else if (angle_rad_diff < 0)
                    {
                        //'OBTUSE' angle side,'OUTTER' join
                        //-------------------
                        switch (LineJoinKind)
                        {
                        default: throw new NotSupportedException();

                        case LineJoin.Round:

                            ArcGenerator.GenerateArcNew(positiveSideVectors,
                                                        x1, y1,
                                                        delta_v0v1,
                                                        angle_rad_diff);

                            break;

                        case LineJoin.Miter:
                        {
                            //check mitter limit
                            double cal_mitterLen  = HalfWidth / Math.Sin((Math.PI - angle_rad_diff) / 2);
                            double half_mitterLen = HalfWidth * MitterLimit;
                            if (cal_mitterLen > half_mitterLen)
                            {
                                Vector2 mid_bc      = (vec_b + vec_c) / 2;
                                Vector2 vec_bc      = vec_c - vec_b;
                                Vector2 limit_delta = vec_bc.RotateInDegree(90).NewLength(half_mitterLen);
                                Vector2 mid_bc_n    = mid_bc + limit_delta;


                                Vector2 lim_cutPoint;
                                if (MyMath.FindCutPoint(
                                        vec_a, vec_b,                //a->b
                                        mid_bc_n, mid_bc_n + vec_bc, //b->c
                                        out lim_cutPoint))
                                {
                                    positiveSideVectors.Add(new Vector(lim_cutPoint.x, lim_cutPoint.y));
                                }
                                else
                                {
                                }

                                if (MyMath.FindCutPoint(
                                        vec_c, vec_d,                //a->b
                                        mid_bc_n, mid_bc_n + vec_bc, //b->c
                                        out lim_cutPoint))
                                {
                                    positiveSideVectors.Add(new Vector(lim_cutPoint.x, lim_cutPoint.y));
                                }
                                else
                                {
                                }
                            }
                            else
                            {
                                positiveSideVectors.Add(new Vector(cutPoint.x, cutPoint.y));
                            }
                        }
                        break;
                        }
                    }
                    else
                    {
                        //angle =0 , same line
                    }
                }
                else
                {
                    //the 2 not cut
                }
            }
            //----------------------------------------------------------------
            if (negativeSideVectors != null)
            {
                delta_v0v1 = -delta_v0v1; //change vector direction***
                delta_v1v2 = -delta_v1v2; //change vector direction***

                Vector2 vec_a = new Vector2(x0 + delta_v0v1.x, y0 + delta_v0v1.y);
                Vector2 vec_b = new Vector2(x1 + delta_v0v1.x, y1 + delta_v0v1.y);
                Vector2 vec_c = new Vector2(x1 + delta_v1v2.x, y1 + delta_v1v2.y);
                Vector2 vec_d = new Vector2(x2 + delta_v1v2.x, y2 + delta_v1v2.y);

                //-------------
                Vector2 cutPoint;
                if (MyMath.FindCutPoint(
                        vec_a, vec_b, //a->b
                        vec_c, vec_d, //b->c
                        out cutPoint))
                {
                    if (angle_rad_diff > 0)
                    {
                        //'ACUTE' angle side
                        //for negative side, this is outter join
                        //-------------------
                        switch (LineJoinKind)
                        {
                        case LineJoin.Round:
                            ArcGenerator.GenerateArcNew(negativeSideVectors,
                                                        x1, y1,
                                                        delta_v0v1,
                                                        angle_rad_diff);
                            break;

                        case LineJoin.Miter:
                        {
                            //see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit

                            double cal_mitterLen  = HalfWidth / Math.Sin((Math.PI - angle_rad_diff) / 2);
                            double half_mitterLen = HalfWidth * MitterLimit;
                            if (cal_mitterLen > half_mitterLen)
                            {
                                Vector2 mid_bc      = (vec_b + vec_c) / 2;
                                Vector2 vec_bc      = vec_c - vec_b;
                                Vector2 limit_delta = vec_bc.RotateInDegree(-90).NewLength(half_mitterLen);
                                Vector2 mid_bc_n    = mid_bc + limit_delta;


                                Vector2 lim_cutPoint;
                                if (MyMath.FindCutPoint(
                                        vec_a, vec_b,                //a->b
                                        mid_bc_n, mid_bc_n + vec_bc, //b->c
                                        out lim_cutPoint))
                                {
                                    negativeSideVectors.Add(new Vector(lim_cutPoint.x, lim_cutPoint.y));
                                }
                                else
                                {
                                }

                                if (MyMath.FindCutPoint(
                                        vec_c, vec_d,                //a->b
                                        mid_bc_n, mid_bc_n + vec_bc, //b->c
                                        out lim_cutPoint))
                                {
                                    negativeSideVectors.Add(new Vector(lim_cutPoint.x, lim_cutPoint.y));
                                }
                                else
                                {
                                }
                            }
                            else
                            {
                                negativeSideVectors.Add(new Vector(cutPoint.x, cutPoint.y));
                            }
                        }
                        break;
                        }
                    }
                    else if (angle_rad_diff < 0)
                    {
                        //'OBTUSE' angle side
                        //------------
                        //for negative side, this is outter join
                        //inner join share the same cutpoint
                        negativeSideVectors.Add(new Vector(cutPoint.x, cutPoint.y));
                    }
                    else
                    {
                    }
                }
                else
                {
                    //the 2 not cut
                }
            }
        }