PDA

View Full Version : Duplicate drawRoundRect() method doesn't match core drawRoundRect() method



fattymelt
August 28th, 2009, 03:59 PM
My idea was to create a method for drawing rectangle with rounded corners, but while being able to specify which of the four corners (any, all, none,etc.) you wanted to round.

The method below does the trick, but for some reason my corners don't match the same curves that I get using the same radius with drawRoundRect().

In other words, if I call my method (and set all four corners to be rounded) and compare that with the same call to drawRoundRect() the actual curves of the corners are slightly different.

Anyone have some insight into this?



public function drawComplexRoundedRect(startX:int,startY:int,rectW idth:int,rectHeight:int,radius:int,canvas:Sprite,r oundTopLeft:Boolean=false,roundTopRight:Boolean=fa lse,roundBottomLeft:Boolean=false,roundBottomRight :Boolean=false):void{
if(roundTopLeft){
canvas.graphics.moveTo(startX,(startY+radius));
}else{
canvas.graphics.moveTo(startX,startY);
}

if(roundBottomLeft){
canvas.graphics.lineTo(startX,(rectHeight-radius));
canvas.graphics.curveTo(startX,rectHeight,radius,r ectHeight);
}else{
canvas.graphics.lineTo(startX,rectHeight);
}

if(roundBottomRight){
canvas.graphics.lineTo((startX+rectWidth-radius),rectHeight);
canvas.graphics.curveTo((startX+rectWidth),rectHei ght,(startX+rectWidth),(rectHeight-radius));
}else{
canvas.graphics.lineTo((startX+rectWidth),rectHeig ht);
}

if(roundTopRight){
canvas.graphics.lineTo((startX+rectWidth),startY+r adius);
canvas.graphics.curveTo((startX+rectWidth),startY, (rectWidth-radius),startY);
}else{
canvas.graphics.lineTo((startX+rectWidth),startY);
}

if(roundTopLeft){
canvas.graphics.lineTo(startX+radius,startY);
canvas.graphics.curveTo(startX,startY,startX,(star tY+radius));
}else{
canvas.graphics.lineTo(startX,startY);
}
}then compare


var canvas:Sprite = new Sprite;
drawComplexRoundedRect(0,0,200,200,25,canvas,true, true,true,true);with


var canvas:Sprite = new Sprite;
canvas.drawRoundRect(0,0,200,200,25);and you will see the two rectangles are not identical.

senocular
August 28th, 2009, 04:20 PM
I imagine the corners in the native drawRoundRect use a higher fidelity with more curves. You're just using one.

fattymelt
August 28th, 2009, 04:55 PM
I guess mx.utils.GraphicUtils has a similar class. Although I haven't tried it...


public static function drawRoundRectComplex(graphics:Graphics, x:Number, y:Number,
width:Number, height:Number,
topLeftRadius:Number, topRightRadius:Number,
bottomLeftRadius:Number, bottomRightRadius:Number):void
{
var xw:Number = x + width;
var yh:Number = y + height;

// Make sure none of the radius values are greater than w/h.
// These are all inlined to avoid function calling overhead
var minSize:Number = width < height ? width * 2 : height * 2;
topLeftRadius = topLeftRadius < minSize ? topLeftRadius : minSize;
topRightRadius = topRightRadius < minSize ? topRightRadius : minSize;
bottomLeftRadius = bottomLeftRadius < minSize ? bottomLeftRadius : minSize;
bottomRightRadius = bottomRightRadius < minSize ? bottomRightRadius : minSize;

// Math.sin and Math,tan values for optimal performance.
// Math.rad = Math.PI / 180 = 0.0174532925199433
// r * Math.sin(45 * Math.rad) = (r * 0.707106781186547);
// r * Math.tan(22.5 * Math.rad) = (r * 0.414213562373095);
//
// We can save further cycles by precalculating
// 1.0 - 0.707106781186547 = 0.292893218813453 and
// 1.0 - 0.414213562373095 = 0.585786437626905

// bottom-right corner
var a:Number = bottomRightRadius * 0.292893218813453; // radius - anchor pt;
var s:Number = bottomRightRadius * 0.585786437626905; // radius - control pt;
graphics.moveTo(xw, yh - bottomRightRadius);
graphics.curveTo(xw, yh - s, xw - a, yh - a);
graphics.curveTo(xw - s, yh, xw - bottomRightRadius, yh);

// bottom-left corner
a = bottomLeftRadius * 0.292893218813453;
s = bottomLeftRadius * 0.585786437626905;
graphics.lineTo(x + bottomLeftRadius, yh);
graphics.curveTo(x + s, yh, x + a, yh - a);
graphics.curveTo(x, yh - s, x, yh - bottomLeftRadius);

// top-left corner
a = topLeftRadius * 0.292893218813453;
s = topLeftRadius * 0.585786437626905;
graphics.lineTo(x, y + topLeftRadius);
graphics.curveTo(x, y + s, x + a, y + a);
graphics.curveTo(x + s, y, x + topLeftRadius, y);

// top-right corner
a = topRightRadius * 0.292893218813453;
s = topRightRadius * 0.585786437626905;
graphics.lineTo(xw - topRightRadius, y);
graphics.curveTo(xw - s, y, xw - a, y + a);
graphics.curveTo(xw, y + s, xw, y + topRightRadius);
graphics.lineTo(xw, yh - bottomRightRadius); }