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:
i've tried using path.addcurvetopoint
, path.addarc
can't seem them work way want. appreciated.
edit
i played around path.addcurvetopoint
, looks this:
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:
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();
: 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
Post a Comment