Once again you can do this with differentiation and get an 'exact' answer, and 
I suspect it is more effecient to do so than buddy4n's suggestion of tracking 
the path.

Differentiating the parametric equations

x = pu³ + qu² + ru + s
y = wu³ + xu² + yu + z

gives 
dx/du = 3pu² + 2qu + r and
dy/du = 3wu² + 2xu + y

from which values of u can be found for the turning points (dx/du = 0) by the 
standard quadratic formula (x = [-b±sqrt(b²-4ac)]/2a) as

u = [-2q ± sqrt(4q²-12pr)] / 6p = [-q ± sqrt(q²-3pr)] / 3p (for x) and v = [-x 
± sqrt(x²-3wy)] / 3w (for y)

There are two values for each of u and v, one for the minimum and one for the 
maximum. For each value, if it is less than 0 then the beginning of the curve 
is the min/max, if it is greater than 1 then the end is, and if it is between 
then you need to calculate the appropriate x (or y) by using u (or v) in the 
initial equations.

Now, unfortunately, this is for a cubic curve of infinite length, and sometimes 
it doesn't work.
 - If there are no turning points in one direction, there will be no solutions 
for u (q²-3pr is negative). In this case use the values at the endpoints.
 - If either endpoint is outside the bounding box you just calculated, expand 
the bounding box to accommodate it.

The bounding box of a whole path is obviously the 'bounding box of bounding 
boxes'. This method should give the box for a cubic Bézier segment.

This is the C# I use for this problem. Alas I used different names for the 
variables: 
 t is the parametric variable (u above)
 a, b, c are the (2D) constants of the equation (a=(p, w); b = (q, x) ... etc 
from above)

                public RectangleF GetBoundingBox(){
                        RectangleF res = new RectangleF();
                        
                        // Find values of t for max x
                        // t = [-b ± sqrt(b²-3ac)] / 3a (if a != 0)
                        // t = -c/2b (if a = 0)
                        double tx1, tx2, ty1, ty2;
                        if(a.X != 0){
                                tx1 = (-b.X + Math.Sqrt((b.X*b.X) - (3 * a.X * 
c.X))) / (3 * a.X);
                                tx2 = (-b.X - Math.Sqrt((b.X*b.X) - (3 * a.X * 
c.X))) / (3 * a.X);
                        } else if (b.X != 0) {
                                tx1 = -c.X / (2.0 * b.X);
                                tx2 = 0;
                        } else {
                                tx1 = 0; tx2 = 1;
                        }
                        
                        if(Double.IsNaN(tx1)){ tx1 = 0; tx2 = 1; }
                        
                        if(a.Y != 0){
                                ty1 = (-b.Y + Math.Sqrt((b.Y*b.Y) - (3 * a.Y * 
c.Y))) / (3 * a.Y);
                                ty2 = (-b.Y - Math.Sqrt((b.Y*b.Y) - (3 * a.Y * 
c.Y))) / (3 * a.Y);
                        } else if(b.Y != 0) {
                                ty1 = -c.Y / (2.0 * b.Y);
                                ty2 = 0;
                        } else {
                                ty1 = 0; ty2 = 1;
                        }
                        
                        if(Double.IsNaN(ty1)){ ty1 = 0; ty2 = 1; }
                        
                        Console.WriteLine("--BOUNDING BOX--\n" + this + "\nbb: 
" + "\ntx1 = "+tx1+"; tx2 = "+tx2+"; ty1 = "+ty1+"; ty2 = "+ty2+"\na = "+a+"; b 
= "+b+"; c = "+c);
                        
                        if(tx1 < 0) tx1 = 0; else if(tx1 > 1) tx1 = 1;
                        if(tx2 < 0) tx2 = 0; else if(tx2 > 1) tx2 = 1;
                        if(ty1 < 0) ty1 = 0; else if(ty1 > 1) ty1 = 1;
                        if(ty2 < 0) ty2 = 0; else if(ty2 > 1) ty2 = 1;
                        
                        float minX = this[(float)tx1].X;
                        float maxX = this[(float)tx2].X;
                        if(maxX < minX){ float temp = minX; minX = maxX; maxX = 
temp; }
                        
                        float minY = this[(float)ty1].Y;
                        float maxY = this[(float)ty2].Y;
                        if(maxY < minY){ float temp = minY; minY = maxY; maxY = 
temp; }
                        
                        // Make sure the nodes are inside
                        if(p1.X < minX) minX = p1.X; if(p1.X > maxX) maxX = 
p1.X;
                        if(p2.X < minX) minX = p2.X; if(p2.X > maxX) maxX = 
p2.X;
                        if(p1.Y < minY) minY = p1.Y; if(p1.Y > maxY) maxY = 
p1.Y;
                        if(p2.Y < minY) minY = p2.Y; if(p2.Y > maxY) maxY = 
p2.Y;
                        
                        res.X = minX; res.Y = minY;
                        res.Width = maxX - minX; res.Height = maxY - minY;
                        
                        Console.WriteLine("BB is "+res);
                        return res;
                }



------------------------ Yahoo! Groups Sponsor --------------------~--> 
<font face=arial size=-1><a 
href="http://us.ard.yahoo.com/SIG=12h7ebbqi/M=362335.6886445.7839731.1510227/D=groups/S=1706030389:TM/Y=YAHOO/EXP=1124385915/A=2894361/R=0/SIG=13jmebhbo/*http://www.networkforgood.org/topics/education/digitaldivide/?source=YAHOO&cmpgn=GRP&RTP=http://groups.yahoo.com/";>In
 low income neighborhoods, 84% do not own computers. At Network for Good, help 
bridge the Digital Divide!</a>.</font>
--------------------------------------------------------------------~-> 

-----
To unsubscribe send a message to: [EMAIL PROTECTED]
-or-
visit http://groups.yahoo.com/group/svg-developers and click "edit my 
membership"
---- 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/svg-developers/

<*> To unsubscribe from this group, send an email to:
    [EMAIL PROTECTED]

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 


Reply via email to