I have to draw an image using Graphics and Graphics2D. The image is Monstercat

How would you guys suggest I do the parts that have several curves to them? Do I use multiple QuadCurve2D or is there a way to do it in one method?

monstercat_logo_vector_by_lmw_ybc-d63hlvv.png

On a side note, do you guys have any recommendations on a program I could use to find the points where the curves are and such? I'm on a mac at the moment, but at school I'm on windows. Oddly, paint has a grid that has (so far, not well though) been working out.

Recommended Answers

All 2 Replies

I think you will have to create a Shape using multiple arcs, quad curves, maybe even cubic curves. Although cubic curves have the potential to construct this with fewer segments, you may find that it's a lot easier to use simpler curves.
You may also be able to simplify the tail and headband as wide-stroked lines rather than filled shapes.

If you print that large onto a fine grid you can get the end and control points for each quad curve segment - it looks like well under 100 segments to me, so it shouldn't be more than a tedious half hour to code them.

(If you want to score bonus points, you could write a little program to diplay that image in a JFrame and mouse-click segment start/control/end points, and generate the necessary segment definitions directly to a text file. That program shouldn't take much longer than doing it by hand.)

Just for a laugh I hacked this little program to help get the quad curves. Open the bitmap. Click 3 times to define a new curve (start/control/end points). Drag points as required. List of curves is printed after each change - you can change the format to make this more useful (eg print the actual code for a new quad curve ready to paste). Feel free to hack it yourself, it's only 200 lines
J

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.geom.QuadCurve2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * @author JamesCherrill
 */
public class CurveFitter {

    public static void main(String[] args) {
        new CurveFitter();
    }

    CurveFitter() {
        JFrame frame = new JFrame("Close this to exit application");
        frame.add(new FitterPanel(getImageFromFile()));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    Image getImageFromFile() {
        JFileChooser fc = new JFileChooser();
        int returnVal = fc.showOpenDialog(null);
        if (returnVal != JFileChooser.APPROVE_OPTION) {
            System.exit(-1);
        }
        BufferedImage image = null;
        try {
            File f = fc.getSelectedFile();
            image = ImageIO.read(f);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return image;
    }

    class FitterPanel extends JPanel {

        Image image;

        int pointCounter = 0;
        Point2D[] points = new Point2D[3];
        List<Point2D[]> curves = new ArrayList<>();

        Point2D[] selectedCurve = null;
        int selectedPointIndex = 0; // which point in selected curve

        FitterPanel(Image image) {
            this.image = image;
            ClickHandler listener = new ClickHandler();
            this.addMouseListener(listener);
            this.addMouseMotionListener(listener);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(image.getWidth(null), image.getHeight(null));
        }

        void addPoint(Point2D p) {
            points[pointCounter] = p;
            if (++pointCounter >= 3) {
                curves.add(points);
                printCurves();
                pointCounter = 0;
                points = new Point2D[3];
            }
            this.repaint();
        }

        boolean checkAndSetSelected(Point2D point) {
            // is this point one of the existing control points?
            for (Point2D[] points : curves) {
                for (int i = 0; i < points.length; i++) {
                    if (areNear(points[i], point)) {
                        selectedCurve = points;
                        selectedPointIndex = i;
                        pointCounter = 0; // forget any part-complete curve
                        return true;
                    }
                }
            }
            selectedCurve = null;
            selectedPointIndex = 0;
            return false;
        }

        boolean areNear(Point2D p1, Point2D p2) {
            double tolerance = 5; // pixels
            double dx = p1.getX() - p2.getX();
            if (dx < -tolerance || dx > tolerance) {
                return false;
            }
            double dy = p1.getY() - p2.getY();
            if (dy < -tolerance || dy > tolerance) {
                return false;
            }
            return true;
        }

        public void printCurves() {
            System.out.println("\nCurves: (start point, control point, end point)");
            for (Point2D[] points : curves) {
                for (Point2D p : points) {
                    System.out.print((int) p.getX() + "," + (int) p.getY() + "   ");
                }
                System.out.println("");
            }
        }

        @Override
        public void paint(Graphics g) {
            Graphics2D g2D = (Graphics2D) g;
            g2D.drawImage(image, 0, 0, null);
            // draw the curves (points and fitted line)
            for (Point2D[] points : curves) {
                g2D.setColor(Color.blue);
                for (Point2D p : points) {
                    g2D.drawRect((int) p.getX() - 2, (int) p.getY() - 2, 5, 5);
                }
                g2D.setColor(Color.red);
                if (points.length == 3) {  // 3 points == quad curve
                    QuadCurve2D.Double qc = new QuadCurve2D.Double();
                    qc.setCurve(points, 0);
                    g2D.draw(qc);
                }
            }
            // draw the latest points - not part of a curve yet...
            g2D.setColor(Color.green);
            for (int i = 0; i < pointCounter; i++) {
                g2D.drawRect((int) points[i].getX() - 2, (int) points[i].getY() - 2, 5, 5);
            }
            // draw the selected point (if any)
            if (selectedCurve != null) {
                g2D.setColor(Color.cyan);
                Point2D p = selectedCurve[selectedPointIndex];
                g2D.fillRect((int) p.getX() - 3, (int) p.getY() - 3, 7, 7);
            }
        }

        class ClickHandler implements MouseListener, MouseMotionListener {

            @Override
            public void mouseClicked(MouseEvent e) {
                // System.out.println("Click " + e.getX() + "," + e.getY());
                if (selectedCurve == null) {
                    addPoint(e.getPoint());
                }
            }

            @Override
            public void mousePressed(MouseEvent e) {
                checkAndSetSelected(e.getPoint());
                repaint();
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                if (selectedCurve != null) {
                    printCurves();
                }
            }

            @Override
            public void mouseEntered(MouseEvent e) {
            }

            @Override
            public void mouseExited(MouseEvent e) {
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                if (selectedCurve != null) {
                    selectedCurve[selectedPointIndex] = e.getPoint();
                    repaint();
                }
            }

            @Override
            public void mouseMoved(MouseEvent e) {
            }
        }

    }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.