Wednesday 31 December 2008



Added some more animation features to my Bezier Flower Demo - which you can view by clicking on the link below -
View Petal Demo @ http://www.javaimage.co.uk/flower.html

Chapter 58

Chapter 58 Bezier Curves 2


Plan

1 - Recap on some key points from last chapter (keep up to date with philomath’s blog)


Processing uses cubic bezier - 2 Anchor points (AP) and 2 control points (CP)

(Make the point that ‘cubic bezier’ => MAXIMUM number of turning points is 2)

Joining two bezier curves together - HOW to KEEP Joined curve ‘smooth’ by making common anchor point (AP) and last control point (CP) of 1st curve and 1st control point of 2nd curve on a straight line - introduce the term ‘colinear’ - Refer back to chapter 24 equation of a straight line.


Demo program 1

Devise a simple program which allows you to plot 7 points - and uses cubic beziers to draw a curve - allow this curve to remove sharp turns at common anchor point by moving either the common anchor point or the last control point of the 1st curve or first control point of the second curve so all 3 points are colinear - by hitting the ‘S’ (S for Smooth) key.

Explain how we can move one of the CPs or common AP using the equation of a straight line y = mx + c



Demo Program 2


Compare a pair of joined cubic beziers with a complex poly - trace both

MORE HERE


Demo Program 3

Using Bezier Curves for animation - describe a Processing program which plots an animating flower or flowers - using CBC - Describe the maths (O Level) to work out where the Anchor Points and control points are to draw one petal of a flower -


A DIAGRAM IS VERY IMPORTANT HERE -

SHOWING A CIRCLE WITH A SEGMENT - TWO RADIUS LINES AT AN ANGLE WITH THEIR TANGENT LINES GOING OUT IN OPPOSITE DIRECTIONS AND ANOTHER TWO LINES RADIATING FROM THE TANGENT POINTS AT A GIVEN ‘TILT’ ANGLE.



Explain the maths in terms of straight lines - but also give an alternative mathematical method using CROSS product (to work out tangent) and matrices to rotate the tangents to a given tilt angle.

Monday 29 December 2008

Flower Bezier curves

Managed to lose my Bezier demo (Flower/Spiral generator) in November - (damn you 'Time Machine') - Actually, it turned out to be a good thing, as it made me rethink the maths - in terms of Vectors rather than equations of straight lines. The four control points for the cubic bezier are calculated by working out the tangents to lines radiating from the centre of a circle. Using the radius line and its tangent - we work out an orthogonal matrix - applying a 'tilt' (rotation matrix) to squash or expand the petal.
My lost code was horrible - all sorts of case statements to deal with angle quadrants.


The following code - is the very start of my new Demo program




int displayWidth,displayHeight ;
String mode ;
float CX,CY ;


float degreesToRadians(float th)
{
return PI * th /180.0f ;
}



float translateX(float x)
{
return x+CX ;
}


float translateY(float y)
{
return -y+displayHeight-CY ;
}


PVector [] calcControlPoints(float angle,float ro,float radius,float tilt,float petalLength)
{

PVector [] bezControlPoints = new PVector[4] ;

float halfRo = ro / 2.0f ;

PVector[] cPoints = calcPetalPointPair(angle-halfRo,tilt,petalLength) ;
PVector startPt = cPoints[0] ;
PVector fPoint = cPoints[1] ;


bezControlPoints[0] = new PVector(startPt.x * radius,startPt.y * radius) ;
bezControlPoints[1] = new PVector(startPt.x * radius + fPoint.x,startPt.y * radius + fPoint.y) ;



PVector [] cPoints2 = calcPetalPointPair(angle+halfRo,-tilt,petalLength) ;
startPt = cPoints2[0] ;
fPoint = cPoints2[1] ;

bezControlPoints[3] = new PVector(startPt.x * radius,startPt.y * radius) ;
bezControlPoints[2] = new PVector(startPt.x * radius + fPoint.x,startPt.y * radius + fPoint.y) ;


return bezControlPoints ;

}


void drawBezier(PVector [] cps)
{
drawBezier(cps[0].x,cps[0].y,cps[1].x,cps[1].y,cps[2].x,cps[2].y,cps[3].x,cps[3].y) ;
}

void drawBezier(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)
{
noFill() ;
stroke(0,0,0) ;
bezier(translateX(x1),translateY(y1),
translateX(x2),translateY(y2),
translateX(x3),translateY(y3),
translateX(x4),translateY(y4)) ;



}


void drawControlPoints(PVector[] cps)
{
stroke(255,0,0) ;
drawLine(cps[0].x,cps[0].y,cps[1].x,cps[1].y) ;
stroke(0,255,0) ;
drawLine(cps[2].x,cps[2].y,cps[3].x,cps[3].y) ;

}



PVector[] calcPetalPointPair(float angle,float tilt,float petalLength)
{


PVector startPt = new PVector(1.0*sin(degreesToRadians(angle)),1.0*cos(degreesToRadians(angle)));


PVector vert = new PVector(0,0,1.0f) ; // Unit Vector Perp to XY Plane
PVector nCPc = startPt.cross(vert) ; // Calculate Tangent to Circle at startPt.x,startPt.y


PMatrix2D iMat = new PMatrix2D() ;

iMat.rotate(degreesToRadians(tilt < 0 ? 180+tilt : tilt)) ; // Petal Tilt


PMatrix2D cMat = new PMatrix2D(nCPc.x,startPt.x,0f,nCPc.y,startPt.y,0.0f) ;

// Matrix
// | nCPc.x startx |
// | nCPc.y starty |


cMat.preApply(iMat) ; // Apply our orthog axis to the rotation matrix


PVector fPoint = new PVector() ;
PVector sPoint = new PVector(petalLength,0) ; // Petal Length

cMat.mult(sPoint,fPoint) ; // Apply Full transformation to petal Vector

PVector [] points = new PVector[2] ;
points[0] = startPt ;
points[1] = fPoint ;

return points;

}





void setup()
{

mode = JAVA2D ;


displayHeight = screen.height/2 ;
displayWidth = screen.width/2 ;
CX = displayWidth / 2 ;
CY = displayHeight / 2 ;

size(displayWidth, displayHeight,mode);
loop() ;

}

void drawLine(float x,float y,float x2,float y2) {
line(translateX(x),translateY(y),translateX(x2),translateY(y2)) ;
}

void drawCircle(float x,float y,float rad)
{
ellipse(translateX(x), translateY(y), rad,rad) ;
}




void draw() {

background(255);
float dt = 1/frameRate ; // We should calculate dt - time passed since last update-draw

float radius = 20.0f ;
float tilt = 70.0f ;
float petalLength = 250.0f ;
float ro = 15.0f ;
float step = 7.0f ;
float numpetals = 360.0f / step ;

noFill() ;
ellipseMode(RADIUS) ;
stroke(0,0,0) ;
drawCircle(0,0,radius) ;

for (float angle = 0.0f ; angle < step*numpetals ; angle+=step)
{
PVector [] cps = calcControlPoints(angle,ro,radius,tilt,petalLength) ;
drawBezier(cps) ;
}




}