Forum Stats

  • 3,853,602 Users
  • 2,264,244 Discussions
  • 7,905,405 Comments

Discussions

Help with Bezier curve algorithm, n amount of points?

2»

Comments

  • 807599
    807599 Member Posts: 49,986
    ok, I have this written. I have one error left, that I am not sure how to handle.

    this is in the method bezier(.....)`
    variable bezCurvePt might not have been initialized
    computeBezPt(u,bezCurvePt,nCtrlPts, ctrlPts, c);
    ^
    1 error

    How should I change it?

    import java.applet.*;
    import java.awt.*;
    import java.lang.Math;
    import java.awt.Point;
    import java.awt.Graphics;
    import java.io.*;
    
    
    public class Bezier extends Applet
    {
    
        public class wcPt3D
        {
            double x, y, z;
    
    
            public wcPt3D(double xIN,double yIN, double zIN)
            {
                x = xIN;
                y=yIN;
                z=zIN;
            }
        }
    
    
    
        public void init()
        {
        }
    
        public void paint(Graphics g)
        {
    
            int nCtrlPoints = 4;
            int nBezCurvePts = 1000;
    
            //wcPt3D ctrlPts[] = {{-40.0, -40.0, 0.0}, {-10.0, 200.0, 0.0},
            //                                   { 10.0, 200.0, 0.0}, { 40.0, 40.0 , 0.0}};
    
            wcPt3D [] ctrlPts = {new wcPt3D(-400.0,-40.0,0.0), new wcPt3D(-100.0, 200.0, 0.0), new wcPt3D( 100.0, 200.0, 0.0),
                                 new wcPt3D( 400.0, 400.0 , 0.0)};
    
    
            bezier(ctrlPts, nCtrlPoints, nBezCurvePts, g);
    
        }
    
    
      public void binomialCoeffs(int n, int[] c)
        {
            int k, j;
    
            for(k = 0; k<=n; k++)
                {
                    //compute n!/k!(n-k)!)
    
                    c[k] = 1;
                    for(j = n; j>= k+1; j--)
                        c[k] *=j;
                    for(j = n -k; j>=2; j--)
                        c[k] /=j;
                }
        }
    
        public void computeBezPt(float u, wcPt3D  bezPt, int nCtrlPts, wcPt3D[]  ctrlPts, int [] c)
        {
    
            int k;
            int n = nCtrlPts - 1;
            double bezBlendFcn;
    
            for(k=0; k< nCtrlPts; k++)
                {
                    bezBlendFcn = c[k] * Math.pow(u, k) * Math.pow(1-u, n-k);
                    bezPt.x += ctrlPts[k].x * bezBlendFcn;
                    bezPt.y += ctrlPts[k].y * bezBlendFcn;
                }
        }
    
        public void bezier(wcPt3D[] ctrlPts, int nCtrlPts, int nBezCurvePts, Graphics g)
        {
            wcPt3D bezCurvePt;
            float u;
            int [] c;
            int  k;
    
            c = new int[nCtrlPts];
    
            binomialCoeffs(nCtrlPts -1, c);
    
            for(k = 0; k<= nBezCurvePts; k++)
                {
                    u = (float)k / (float)nBezCurvePts;
                    computeBezPt(u,bezCurvePt,nCtrlPts, ctrlPts, c);
                    g.fillRect((int)bezCurvePt.x,(int)bezCurvePt.y, 1, 1);
    
                }
    
    
    
        }
    
    
    
    
    
    }//end class applet Bezier
  • 807599
    807599 Member Posts: 49,986
    edited Nov 21, 2006 2:52AM
    variable bezCurvePt might not have been initialized
    computeBezPt(u,bezCurvePt,nCtrlPts, ctrlPts, c);
    ^
    1 error
    You need to construct one with default values before you use it as an
    argument. Or, alternatively, have computeBezPt() construct one and return it.
  • 807599
    807599 Member Posts: 49,986
    The book has it the exact way I do and somehow it works--the book coded with opengl though.

    I am not sure what you mean. I gave the class values in the paint method up top.
  • 807599
    807599 Member Posts: 49,986
    The book has it the exact way I do and somehow it works--the book coded with opengl though.
    1. No it doesn't.
    2. OpenGL has nothing to do with it - all that handles is rendering. The issue here is C struct type vs Java reference type.
    3. I already gave you a complete list of the changes you need to make to the C code.
  • 807599
    807599 Member Posts: 49,986
    //  <applet code="B" width="400" height="400"></applet>
    import java.applet.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.Ellipse2D;
     
    public class B extends Applet
    {
        wcPt3D[] ctrlPts =
        {
            new wcPt3D( 20.0,  20.0, 0.0),    new wcPt3D( 360.0,  20.0, 0.0),
            new wcPt3D( 20.0, 340.0, 0.0),    new wcPt3D( 360.0, 340.0, 0.0)
        };
        int nCtrlPoints = ctrlPts.length;
        int nBezCurvePts = 1000;
        int[] c;
     
        public void init()
        {
            c = new int[nCtrlPoints];
            binomialCoeffs(nCtrlPoints -1, c);
        }
     
        public void paint(Graphics g)
        {
            super.paint(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            for(int k = 0; k <= nBezCurvePts; k++)
            {
                float u = (float)k / (float)nBezCurvePts;
                wcPt3D bezCurvePt = computeBezPt(u);
                g.fillRect((int)bezCurvePt.x, (int)bezCurvePt.y, 1, 1);
            }
            g2.setPaint(Color.red);
            for(int j = 0; j < ctrlPts.length; j++)
            {
                wcPt3D p = ctrlPts[j];
                g2.fill(new Ellipse2D.Double(p.x-2, p.y-2, 4, 4));
            }
        }
     
        public void binomialCoeffs(int n, int[] c)
        {
            for(int k = 0; k <= n; k++)
            {
                //compute n!/k!(n-k)!)
                c[k] = 1;
                for(int j = n; j>= k+1; j--)
                    c[k] *=j;
                for(int j = n -k; j>=2; j--)
                    c[k] /=j;
            }
        }
     
        public wcPt3D computeBezPt(float u)
        {
            wcPt3D bezPt = new wcPt3D(0,0,0);
            int n = nCtrlPoints - 1;
            for(int k = 0; k < nCtrlPoints; k++)
            {
                double bezBlendFcn = c[k] * Math.pow(u, k) * Math.pow(1-u, n-k);
                bezPt.x += ctrlPts[k].x * bezBlendFcn;
                bezPt.y += ctrlPts[k].y * bezBlendFcn;
            }
            return bezPt;
        }
     
        public class wcPt3D
        {
            double x, y, z;
     
            public wcPt3D(double xIN, double yIN, double zIN)
            {
                x = xIN;
                y = yIN;
                z = zIN;
            }
        }
     
        public static void main(String[] args)
        {
            Applet applet = new B();
            Frame f = new Frame();
            f.addWindowListener(closer);
            f.add(applet);
            f.setSize(400,400);
            f.setLocation(200,200);
            applet.init();
            f.setVisible(true);
        }
     
        private static WindowListener closer = new WindowAdapter()
        {
            public void windowClosing(WindowEvent e)
            {
                System.exit(0);
            }
        };
    }
  • 807599
    807599 Member Posts: 49,986
    import java.awt.*;
    import java.awt.geom.*;
    import javax.swing.*;
     
    public class B2 extends JApplet {
        public void init() {
            JTabbedPane tabbedPane = new JTabbedPane();
            tabbedPane.addTab("GeneralPath", new BezierPanel());
            tabbedPane.addTab("CubicCurve2D", new CurvePanel());
            Container cp = getContentPane();
            cp.setLayout(new BorderLayout());
            cp.add(tabbedPane);
        }
     
        public static void main(String[] args) {
            JApplet applet = new B2();
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(applet);
            f.setSize(400,400);
            f.setLocation(200,200);
            applet.init();
            f.setVisible(true);
        }
    }
     
    class BezierPanel extends JPanel {
        GeneralPath path;
     
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            if(path == null)
                initPath();
            g2.draw(path);
        }
     
        private void initPath() {
            int w = getWidth();
            int h = getHeight();
            Point2D.Double p1 = new Point2D.Double();
            p1.x = w/4.0;
            p1.y = h/16.0;
            Point2D.Double cp1 = new Point2D.Double();
            cp1.x = w/4.0;
            cp1.y = h*3/2.0;
            Point2D.Double cp2 = new Point2D.Double();
            cp2.x = w/3.0;
            cp2.y = h/4.0;
            Point2D.Double p2 = new Point2D.Double();
            p2.x = w*15/16.0;
            p2.y = h/4.0;
            Point2D.Double[] points = { p1, cp1, cp2, p2 };
            BezierCurve curve = new BezierCurve(points, w);
            Point2D.Double[] p = curve.getCurvePoints();
            path = new GeneralPath();
            for(int j = 0; j < p.length; j++) {
                if(j == 0)
                    path.moveTo((float)p[j].x, (float)p[j].y);
                else
                    path.lineTo((float)p[j].x, (float)p[j].y);
            }
        }
    }
     
    /**
     * Your C class translated into Java.
     * For similar code in java see the Field Detail for
     * the SEG_CUBICTO field in the PathIterator class api.
     */
    class BezierCurve {
        Point2D.Double[] cp;
        int numberOfPoints;
        Point2D.Double[] curvePoints;
     
        public BezierCurve(Point2D.Double[] cp, int numPoints) {
            this.cp = cp;
            numberOfPoints = numPoints;
            curvePoints = new Point2D.Double[numPoints];
            computeBezier();
        }
     
        protected Point2D.Double[] getCurvePoints() {
            return curvePoints;
        }
     
        private void computeBezier() {
            double dt = 1.0 / (numberOfPoints - 1);
     
            for(int j = 0; j < numberOfPoints; j++)
                curvePoints[j] = getCurvePoint(j*dt);
        }
     
        private Point2D.Double getCurvePoint(double t)
        {
            Point2D.Double result = new Point2D.Double();
     
            /* calculate the polynomial coefficients */
            double cx = 3.0 * (cp[1].x - cp[0].x);
            double bx = 3.0 * (cp[2].x - cp[1].x) - cx;
            double ax = cp[3].x - cp[0].x - cx - bx;
     
            double cy = 3.0 * (cp[1].y - cp[0].y);
            double by = 3.0 * (cp[2].y - cp[1].y) - cy;
            double ay = cp[3].y - cp[0].y - cy - by;
     
            /* calculate the curve point at parameter value t */
            double tSquared = t * t;
            double tCubed = tSquared * t;
     
            result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
            result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
     
            return result;
        }
    }
     
    class CurvePanel extends JPanel {
        CubicCurve2D curve;
     
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                RenderingHints.VALUE_ANTIALIAS_ON);
            if(curve == null)
                initCurve();
            g2.draw(curve);
        }
     
        private void initCurve() {
            int w = getWidth();
            int h = getHeight();
            double x1 = w/4.0;
            double y1 = h*3/4.0;
            double ctrlx1 = -50.0;
            double ctrly1 = h/16.0;
            double ctrlx2 = w + 50.0;
            double ctrly2 = h/16.0;
            double x2 = w*3/4.0;
            double y2 = h*3/4.0;
            curve = new CubicCurve2D.Double(x1, y1, ctrlx1, ctrly1,
                                            ctrlx2, ctrly2, x2, y2);
        }
    }
This discussion has been closed.