绘制曲线一点一点 [英] Drawing curve bit by bit

查看:108
本文介绍了绘制曲线一点一点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要绘制一条曲线,知道我每x毫秒或x秒接收一次点数,并且每次收到一个新点时曲线向左移动一个像素。我正在使用Bezier算法从我收到的点绘制曲线,所以我需要至少三个点才能开始。我想知道如何在图像上一点一点地绘制曲线。

I need to draw a curve, knowing that I receive points every x milliseconds or x seconds, and that the curve is moving to the left by one pixel each time I receive a new point. I'm using the Bezier algorithm to draw the curve from the points I receive, so I need at least three points to start. I would like to know how to proceed to draw the curve bit by bit on an image.

这就是我现在正在做的事情:

This is what I'm doing right now:

int xPos = 0;
Point2D.Double[] points = new Point2D.Double[listYpos.size()];

for (int i = 0; i < listYpos.size(); i++) {
    points[i] = new Point2D.Double(i, listYpos.get(i));
}

if (curveImg == null) {
    curveImg = gc.createCompatibleImage(imageWidth, imageHeight, Transparency.BITMASK);
}

if (points.length > 3) {
    Graphics2D gImg = (Graphics2D) curveImg.getGraphics();
    renderCurve(gImg, Arrays.copyOfRange(points, listYpos.size() - 4, listYpos.size() - 1));
    gImg.dispose();
}

AffineTransform at = g.getTransform();
at.scale(-1, 1);
at.translate(-xPos++, listYpos.get(listYpos.size() - 1));

g.drawImage(curveImg, at, null);

每次每x毫秒或x秒收到一个新点时,都会调用此方法。

This method is called each time a new point is received every x milliseconds or x seconds.

推荐答案

我认为 gImg.dispose();

也许这段代码可以帮助你(来自old.forums.sun.com)

maybe this code can help you with that (from old.forums.sun.com)

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import javax.swing.*;

public class BezierTest {

    private class Animator implements ActionListener {

        private double distance = 0;
        private boolean moveTo = true;
        private ArrayList<Point2D> points = new ArrayList<Point2D>();
        private double step = -1;
        private double steps;
        private Timer timer = new Timer(0, this);

        @Override
        public void actionPerformed(ActionEvent e) {
            step++;
            if (step <= steps) {
                double t = step / steps;
                Point2D newPoint = computeBezierPoint(new Point2D.Double(), t, curvePoints);
                marks[marks.length - 1].setFrame(newPoint.getX() - 5, newPoint.getY() - 5, 10, 10);
                points.add(newPoint);
                if (moveTo) {
                    path.moveTo(newPoint.getX(), newPoint.getY());
                    moveTo = false;
                } else {
                    path.lineTo(newPoint.getX(), newPoint.getY());
                }
                lines[3] = new Line2D.Double(computePointOnLine(lines[0], t), computePointOnLine(lines[1], t));
                lines[4] = new Line2D.Double(computePointOnLine(lines[1], t), computePointOnLine(lines[2], t));
                lines[5] = new Line2D.Double(computePointOnLine(lines[3], t), computePointOnLine(lines[4], t));
                // The maximum distance encountered between the results of two calculation methods.
                // newPoint from computeBezierPoint() the other via the lines method
                distance = Math.max(distance, newPoint.distance(computePointOnLine(lines[5], t)));
                demoComponent.repaint();
            } else {
                timer.stop();
                animationButton.setEnabled(true);
                if (distance > 0d) {
                    System.out.println("Maximum difference " + distance);
                }
            }
        }

        public void init() {
            timer.stop();
            animationButton.setEnabled(false);
            steps = sliderStep.getValue();
            step = -1;
            distance = 0;
            moveTo = true;
            path = new Path2D.Double();
            int sleepTime = (int) Math.round(1000d * sliderDuration.getValue() / steps);
            timer.setDelay(sleepTime);
            timer.setInitialDelay(0);
            timer.start();
        }

        private Point2D computeBezierPoint(Point2D rv, double t,
                Point2D... curve) {
            if (rv == null) {
                rv = new Point2D.Double();
            } else {
                rv.setLocation(0, 0);
            }
            int n = curve.length - 1;
            double oneMinusT = 1.0 - t;
            for (int index = 0; index < curve.length; index++) {
                double multiplier = index == 0 || index == n ? 1 : StrictMath.min(n - index, index) * n;
                multiplier *= StrictMath.pow(t, index) * StrictMath.pow(oneMinusT, n - index);
                rv.setLocation(rv.getX() + multiplier * curve[index].getX(), rv.getY() + multiplier * curve[index].getY());
            }
            return rv;
        }

        private Point2D computePointOnLine(Line2D line, double t) {
            return new Point2D.Double((line.getX2() - line.getX1()) * t + line.getX1(), (line.getY2() - line.getY1()) * t + line.getY1());
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new BezierTest().createGUI();
            }
        });
    }
    private final JButton animationButton = new JButton(new AbstractAction("Start animation") {

        private static final long serialVersionUID = 1L;

        @Override
        public void actionPerformed(ActionEvent e) {
            animator.init();
        }
    });
    private final Animator animator = new Animator();
    private Point2D[] curvePoints = new Point2D[]{new Point(10, 50), new Point(190, 10), new Point(190, 190), new Point(10, 150)};
    private JComponent demoComponent = new JComponent() {

        private static final long serialVersionUID = 1L;

        {
            setPreferredSize(new Dimension(400, 400));
            addComponentListener(new ComponentAdapter() {

                @Override
                public void componentResized(ComponentEvent e) {
                    int w = getWidth();
                    int h = getHeight();
                    recalculateAfterResize(w, h);
                }
            });
        }

        @Override
        protected void paintComponent(Graphics g) {
            if (isVisible()) {
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, getWidth(), getHeight());
                super.paintComponent(g);
                paintBezier(g);
            }
        }
    };
    private Line2D[] lines = new Line2D[6];
    private final Ellipse2D[] marks;
    private Path2D path;
    private final JSlider sliderDuration = createSlider(1, 20, 2, "Duration in seconds", 9, 1);
    private final JSlider sliderStep = createSlider(8, 128, 64, "Animation steps", 16, 1);
    private Path2D totalCurve;

    {
        marks = new Ellipse2D[curvePoints.length + 1];
        for (int index = 0; index < marks.length; index++) {
            marks[index] = new Ellipse2D.Double();
        }
    }

    private void createGUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(demoComponent, BorderLayout.CENTER);
        JToolBar toolBar = new JToolBar();
        toolBar.add(animationButton);
        toolBar.add(sliderStep);
        toolBar.add(sliderDuration);
        frame.add(toolBar, BorderLayout.PAGE_START);
        frame.pack();
        frame.setLocation(150, 150);
        frame.setVisible(true);
    }

    private JSlider createSlider(int min, int max, int value, String title, int major, int minor) {
        JSlider slider = new JSlider(min, max, value);
        slider.setBorder(BorderFactory.createTitledBorder(title));
        slider.setMajorTickSpacing(major);
        // slider.setMinorTickSpacing(minor);
        slider.setPaintLabels(true);
        slider.setPaintTicks(true);
        return slider;
    }

    private void paintBezier(Graphics g) {
        Path2D path1 = this.path;
        if (path1 != null) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(Color.GREEN);
            for (Shape mark : marks) {
                g2.fill(mark);
            }
            g2.setStroke(new BasicStroke(2f));
            g2.setColor(Color.BLACK);
            for (Shape mark : marks) {
                g2.draw(mark);
            }
            g2.setStroke(new BasicStroke(0f));
            g2.draw(totalCurve);
            g2.setStroke(new BasicStroke(1f));
            g2.setColor(Color.RED);
            g2.draw(path1);
            g2.setStroke(new BasicStroke(.5f));
            g2.setColor(Color.BLACK);
            for (Line2D line : lines) {
                if (line != null) {
                    g2.draw(line);
                }
            }
        }
    }

    private void recalculateAfterResize(int w, int h) {
        curvePoints = new Point2D[]{new Point2D.Double(10, h / 4.0), new Point2D.Double(w - 10, 10), new Point2D.Double(w - 10, h - 10), new Point2D.Double(10, h - h / 4.0)};
        totalCurve = new Path2D.Double();
        totalCurve.moveTo(curvePoints[0].getX(), curvePoints[0].getY());
        totalCurve.curveTo(curvePoints[1].getX(), curvePoints[1].getY(), curvePoints[2].getX(), curvePoints[2].getY(), curvePoints[3].getX(), curvePoints[3].getY());
        for (int index = 0; index < curvePoints.length; index++) {
            marks[index].setFrame(curvePoints[index].getX() - 5, curvePoints[index].getY() - 5, 10, 10);
        }
        marks[marks.length - 1].setFrame(marks[0].getFrame());
        for (int index = 0; index < curvePoints.length - 1; index++) {
            lines[index] = new Line2D.Double(curvePoints[index], curvePoints[index + 1]);
        }
        lines[3] = null;
        lines[4] = null;
        lines[5] = null;
        animator.init();
    }
}

这篇关于绘制曲线一点一点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆