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 } } }