c# - Xamarin iOS CGPath draw polygon with curved/rounded corners -


i'm trying create class draws polygon in custom uiview subclass. have working, want smooth corners rounding them off , i'm not sure how that. here have far:

public class myview : uiview {     private list<cgpoint> points;      public myview(cgrect frame, list<cgpoint> points) : base (frame)     {         this.points = points;     }      public override draw (cgrect rect)     {         cgcontext context = uigraphics.getcurrentcontext();          context.setlinewidth(2);         uicolor.black.setstroke();         uicolor.green.setfill();          cgpath path = new cgpath();         path.addlines(points.toarray());         path.closesubpath();          context.addpath(path);         context.clip();          using (cgcolorspace rgb = cgcolorspace.createdevicergb())         {             cggradient gradient = new cggradient (rgb, new cgcolor[]             {                 new cgcolor(0, 1, 0),                 new cgcolor(0, 0.5f, 0),                 new cgcolor(0, 1, 0),                 new cgcolor(0, 0.5f, 0)             });              context.drawlineargradient(gradient,                 new cgpoint (path.boundingbox.left, path.boundingbox.top),                  new cgpoint (path.boundingbox.right, path.boundingbox.bottom),                  cggradientdrawingoptions.drawsbeforestartlocation);         }     } } 

with points i'm throwing in this:

enter image description here

i've tried using path.addcurvetopoint , path.addarc can't seem them work way want. appreciated.

edit

i played around path.addcurvetopoint , looks this:

enter image description here

it starts off correctly, goes nuts. not sure i'm doing wrong here. here updated draw override:

public override draw (cgrect rect) {     cgcontext context = uigraphics.getcurrentcontext();      context.setlinewidth(2);     uicolor.black.setstroke();     uicolor.green.setfill();      cgpath path = new cgpath();     path.addlines(points.toarray());     path.closesubpath();     // updated section     int count = points.count;      (int x = 1; x < count; x++)     {         var p = points[x];         if (x != 0)         {             var prev = points[x - 1];             if (prev.y != p.y)             {                 if (prev.y > p.y)                 {                     path.addcurvetopoint(prev, new cgpoint(p.x - prev.x, p.y), p);                 }                 else                 {                     //???                 }             }         }     }     // end updated section     context.addpath(path);     context.clip();      using (cgcolorspace rgb = cgcolorspace.createdevicergb())     {         cggradient gradient = new cggradient (rgb, new cgcolor[]         {             new cgcolor(0, 1, 0),             new cgcolor(0, 0.5f, 0),             new cgcolor(0, 1, 0),             new cgcolor(0, 0.5f, 0)         });          context.drawlineargradient(gradient,             new cgpoint (path.boundingbox.left, path.boundingbox.top),              new cgpoint (path.boundingbox.right, path.boundingbox.bottom),              cggradientdrawingoptions.drawsbeforestartlocation);     } } 

update:

with update, see issue now. trying use point list both bézier control points , draw points polygon corners, not work.

the "easiest" way use existing point list control points , create mid-way knots between each control point , add quad curve each segment.

note: harder way use list of points knots , create control points each bezier curve segment. not go here, number of charting systems use article reference , return values getcontrolpoints used control points method addcurvetopoint.

easy way example:

enter image description here

var color = uicolor.red; var color2 = uicolor.white;  var points = new list<cgpoint>() {      new cgpoint(136.49f, 134.6f),     new cgpoint(197.04f, 20.0f),     new cgpoint(257.59f, 20.0f),     new cgpoint(303.0f, 134.6f),     new cgpoint(303.0f, 252.0f),     new cgpoint(28.0f, 252.0f),     new cgpoint(28.0f, 134.6f),     new cgpoint(136.49f, 134.6f) };  uibezierpath polygonpath = new uibezierpath(); polygonpath.moveto(points[0]); polygonpath.addlineto(points[1]); polygonpath.addlineto(points[2]); polygonpath.addlineto(points[3]); polygonpath.addlineto(points[4]); polygonpath.addlineto(points[5]); polygonpath.addlineto(points[6]); polygonpath.closepath(); polygonpath.fill(); color2.setstroke(); polygonpath.linewidth = 10.0f; polygonpath.stroke();  uibezierpath smoothedpath = new uibezierpath(); var m0 = midpoint(points[0], points[1]); smoothedpath.moveto(m0); smoothedpath.addquadcurvetopoint(m0, points[0]); var m1 = midpoint(points[1], points[2]); smoothedpath.addquadcurvetopoint(m1, points[1]); var m2 = midpoint(points[2], points[3]); smoothedpath.addquadcurvetopoint(m2, points[2]); var m3 = midpoint(points[3], points[4]); smoothedpath.addquadcurvetopoint(m3, points[3]); var m4 = midpoint(points[4], points[5]); smoothedpath.addquadcurvetopoint(m4, points[4]); var m5 = midpoint(points[5], points[6]); smoothedpath.addquadcurvetopoint(m5, points[5]); var m6 = midpoint(points[6], points[0]); smoothedpath.addquadcurvetopoint(m6, points[6]);  smoothedpath.addquadcurvetopoint(m0, points[0]);  smoothedpath.closepath();  color.setstroke(); smoothedpath.linewidth = 5.0f; smoothedpath.stroke(); 

original:

1) unsure of how joint smoothing looking, cglinejoin.round linejoinstyle on uibezierpath create subtle look.

2) if need heavy corner smoothing, can manually calculate start/end of each line , add arcwithcenter join each line segment.

3) or without manual corner arc calculations can set heavy line width while using cglinejoin.round , size drawing smaller make increased line width.

example:

var color = uicolor.fromrgba(0.129f, 0.467f, 0.874f, 1.000f);  uibezierpath polygonpath = new uibezierpath(); polygonpath.moveto(new cgpoint(136.49f, 134.6f)); polygonpath.addlineto(new cgpoint(197.04f, 20.0f)); polygonpath.addlineto(new cgpoint(257.59f, 20.0f)); polygonpath.addlineto(new cgpoint(303.0f, 134.6f)); polygonpath.addlineto(new cgpoint(303.0f, 252.0f)); polygonpath.addlineto(new cgpoint(28.0f, 252.0f)); polygonpath.addlineto(new cgpoint(28.0f, 134.6f)); polygonpath.addlineto(new cgpoint(136.49f, 134.6f)); polygonpath.closepath(); polygonpath.linejoinstyle = cglinejoin.round;  color.setfill(); polygonpath.fill(); color.setstroke(); polygonpath.linewidth = 30.0f; polygonpath.stroke(); 

enter image description here

: midpoint method

protected cgpoint midpoint(cgpoint first, cgpoint second) {     var x = (first.x + second.x) / 2;     var y = (first.y + second.y) / 2;     return new cgpoint(x: x, y: y); } 

Comments

Popular posts from this blog

sequelize.js - Sequelize group by with association includes id -

android - Robolectric "INTERNET permission is required" -

java - Android raising EPERM (Operation not permitted) when attempting to send UDP packet after network connection -