如何使用自定义轴类型? (JAVA)

时间:2015-03-24 15:10:19

标签: java function graph awt axis

我想开发一个桌面应用程序,它能够在具有自定义轴的坐标系中绘制给定函数的图形。 例如:用户可以在X轴和Y轴的情况下在线性,对数,指数等轴类型之间进行切换。

  • 你认为Java AWT适合这个目的吗? (我还不知道),
  • 您是否知道可以/应该使用哪些其他技术?
  • 在这种情况下,时间是最重要的,所以我需要最简单的方法..

提前谢谢你, 马顿

2 个答案:

答案 0 :(得分:0)

Swing或JavaFX会优于AWT。

这里是我开发的一些代码,用于在Swing绘图区域上放置笛卡尔坐标系和/或极坐标系。您可以将此作为您想要做的事情的起点。

CoordinateSystem类

package com.ggl.game.utilities;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Point2D;

/**
 * <p>
 * This class creates a Cartesian and Polar coordinate system to overlay a Swing
 * drawing area (usually a <code>JPanel</code>). The user of the class sets a
 * limit as to how far the X axis or the Y axis extends in the negative and
 * positive direction from (0, 0). Point (0, 0) will be placed in the center of
 * the drawing area.
 * </p>
 * <p>
 * Since the drawing area is usually not square, the limit applies to the
 * shorter dimension. The actual limits can be retrieved from this class, and
 * will change if the user of the application changes the drawing area size by
 * maximizing or normalizing the application <code>JFrame</code> window.
 * </p>
 * <p>
 * Using a Cartesian or Polar coordinate system frees the user of this class
 * from having to worry about Swing pixel coordinates.
 * </p>
 * 
 * @author Gilbert G. Le Blanc
 * @version 1.0 - 23 February 2015
 * 
 * @see com.ggl.game.utilities.Polar2D
 * @see java.awt.geom.Point2D
 * @see javax.swing.JFrame
 * @see javax.swing.JPanel
 */
public class CoordinateSystem {

    private double conversionFactor;
    private double xLimit;
    private double yLimit;

    private int height;
    private int width;

    /**
     * <p>
     * This creates a Cartesian and Polar coordinate system over a Swing drawing
     * area (usually a <code>JPanel</code>). If the drawing area is square, the
     * X axis extends from -limit to limit and the Y axis extends from -limit to
     * limit.
     * </p>
     * <p>
     * If the drawing area is not square, then the smaller dimension, either X
     * or Y, extends from -limit to limit. The larger dimension extends beyond
     * the limit in both directions.
     * </p>
     * <p>
     * Since most displays are not square, the X and Y axis will usually have
     * different limits.
     * </p>
     * 
     * @param limit
     *            - The limit of the X and Y axis in a Cartesian coordinate
     *            system.
     * @param width
     *            - The width of the drawing area in pixels.
     * @param height
     *            - The height of the drawing area in pixels.
     */
    public CoordinateSystem(double limit, int width, int height) {
        this.width = width;
        this.height = height;

        if (width > height) {
            this.xLimit = limit * width / height;
            this.yLimit = limit;
            this.conversionFactor = (limit + limit) / (double) height;
        } else if (width < height) {
            this.xLimit = limit;
            this.yLimit = limit * height / width;
            this.conversionFactor = (limit + limit) / (double) width;
        } else {
            this.xLimit = limit;
            this.yLimit = limit;
            this.conversionFactor = (limit + limit) / (double) width;
        }
    }

    /**
     * This method changes the drawing area dimension, along with the X and Y
     * axis limits.
     * 
     * @param dimension
     *            - A <code>Dimension</code> with the new drawing area
     *            dimension.
     */
    public void setDrawingSize(Dimension dimension) {
        setDrawingSize(dimension.width, dimension.height);
    }

    /**
     * This method changes the drawing area width and height, along with the X
     * and Y axis limits.
     * 
     * @param width
     *            - The width of the drawing area in pixels.
     * @param height
     *            - The height of the drawing area in pixels.
     */
    public void setDrawingSize(int width, int height) {
        xLimit = xLimit / this.width * width;
        yLimit = yLimit / this.height * height;

        this.width = width;
        this.height = height;
    }

    /**
     * This method returns the Cartesian coordinate limit for the X axis.
     * 
     * @return The Cartesian coordinate limit for the X axis.
     */
    public double getxLimit() {
        return xLimit;
    }

    /**
     * This method returns the Cartesian coordinate limit for the Y axis.
     * 
     * @return The Cartesian coordinate limit for the Y axis.
     */
    public double getyLimit() {
        return yLimit;
    }

    /**
     * This method converts a Polar coordinate distance and theta angle in
     * radians to a pixel location on a drawing area.
     * 
     * @param distance
     *            - A Polar coordinate distance
     * @param theta
     *            - A Polar coordinate theta angle in radians
     * @return A pixel location on a drawing area.
     */
    public Point convertPolarToPixels(double distance, double theta) {
        return convertToPixels(new Polar2D.Double(distance, theta));
    }

    /**
     * This method converts a Cartesian coordinate x and y to a pixel location
     * on a drawing area.
     * 
     * @param x
     *            - A Cartesian coordinate x.
     * @param y
     *            - A Cartesian coordinate y.
     * @return A pixel location on a drawing area.
     */
    public Point convertPointToPixels(double x, double y) {
        return convertToPixels(new Point2D.Double(x, y));
    }

    /**
     * This method converts a Polar coordinate to a pixel location on a drawing
     * area.
     * 
     * @param polar
     *            - A Polar coordinate.
     * @return A pixel location on a drawing area.
     */
    public Point convertToPixels(Polar2D polar) {
        double x = polar.getDistance() * Math.cos(polar.getTheta());
        double y = polar.getDistance() * Math.sin(polar.getTheta());
        return convertToPixels(new Point2D.Double(x, y));
    }

    /**
     * This method converts a Cartesian coordinate to a pixel location on a
     * drawing area.
     * 
     * @param cartesian
     *            - A Cartesian coordinate.
     * @return A pixel location on a drawing area.
     */
    public Point convertToPixels(Point2D cartesian) {
        int x = (int) Math
                .round((cartesian.getX() + xLimit) / conversionFactor);
        int y = (int) Math.round((-cartesian.getY() + yLimit)
                / conversionFactor);
        return new Point(x, y);
    }

    /**
     * This method converts a pixel location on a drawing area to a Cartesian
     * coordinate.
     * 
     * @param x
     *            - The x pixel location.
     * @param y
     *            - The y pixel location.
     * @return A Cartesian coordinate.
     */
    public Point2D convertToCartesian(int x, int y) {
        return convertToCartesian(new Point(x, y));
    }

    /**
     * This method converts a pixel location on a drawing area to a Cartesian
     * coordinate.
     * 
     * @param point
     *            - The pixel location.
     * @return A Cartesian coordinate.
     */
    public Point2D convertToCartesian(Point point) {
        double x = (double) point.x * conversionFactor - xLimit;
        double y = (double) -point.y * conversionFactor + yLimit;
        return new Point2D.Double(x, y);
    }

    /**
     * This method converts a pixel location on a drawing area to a Polar
     * coordinate.
     * 
     * @param x
     *            - The x pixel location.
     * @param y
     *            - The y pixel location.
     * @return A Polar coordinate.
     */
    public Polar2D convertToPolar(int x, int y) {
        return convertToPolar(new Point(x, y));
    }

    /**
     * This method converts a pixel location on a drawing area to a Polar
     * coordinate.
     * 
     * @param point
     *            - The pixel location.
     * @return A Polar coordinate.
     */
    public Polar2D convertToPolar(Point point) {
        double x = (double) point.x * conversionFactor - xLimit;
        double y = (double) -point.y * conversionFactor + yLimit;
        double distance = Math.sqrt(x * x + y * y);
        double theta = Math.atan2(y, x);
        return new Polar2D.Double(distance, theta);
    }

}

Polar2D类

package com.ggl.game.utilities;

/**
 * The <code>Polar2D</code> class defines a point representing a location in
 * distance, theta angle coordinate space.
 * <p>
 * This class is only the abstract superclass for all objects that store a 2D
 * coordinate. The actual storage representation of the coordinates is left to
 * the subclass.
 * 
 * @version 1.0 - 23 February 2015
 * @author Jim Graham (author of Point2D), Gilbert Le Blanc
 */
public abstract class Polar2D implements Cloneable {
    /**
     * The <code>Float</code> class defines a point specified in float
     * precision.
     */
    public static class Float extends Polar2D {
        /**
         * The distance of this <code>Polar2D</code>.
         * 
         * @since 1.7
         */
        public float distance;
        /**
         * The theta angle of this <code>Polar2D</code>.
         * 
         * @since 1.7
         */
        public float theta;

        /**
         * Constructs and initializes a <code>Polar2D</code> with coordinates
         * (0,&nbsp;0).
         * 
         * @since 1.7
         */
        public Float() {
        }

        /**
         * Constructs and initializes a <code>Polar2D</code> with the specified
         * coordinates.
         * 
         * @param distance
         *            The distance to which to set the newly constructed
         *            <code>Polar2D</code>
         * @param theta
         *            The theta angle in radians to which to set the newly
         *            constructed <code>Polar2D</code>
         * @since 1.7
         */
        public Float(float distance, float theta) {
            this.distance = distance;
            this.theta = theta;
        }

        /**
         * Returns the distance of this <code>Polar2D</code> in
         * <code>double</code> precision.
         * 
         * @return the distance of this <code>Polar2D</code>.
         * @since 1.7
         */
        @Override
        public double getDistance() {
            return (double) distance;
        }

        /**
         * Returns the theta angle in radians of this <code>Polar2D</code> in
         * <code>double</code> precision.
         * 
         * @return the theta angle in radians of this <code>Polar2D</code>.
         * @since 1.7
         */
        @Override
        public double getTheta() {
            return (double) theta;
        }

        /**
         * Returns the theta angle in degrees of this <code>Polar2D</code> in
         * <code>double</code> precision.
         * 
         * @return the theta angle in degrees of this <code>Polar2D</code>.
         * @since 1.7
         */
        @Override
        public double getThetaInDegrees() {
            double degrees = 180D / Math.PI * theta;
            return (degrees < 0D) ? degrees + 360D : degrees;
        }

        /**
         * Sets the location of this <code>Polar2D</code> to the specified
         * <code>double</code> distance and theta angle in radians.
         * 
         * @param distance
         *            The distance to which to set this <code>Polar2D</code>
         * @param theta
         *            The theta angle in radians to which to set this
         *            <code>Polar2D</code>
         * @since 1.7
         */
        @Override
        public void setLocation(double distance, double theta) {
            this.distance = (float) distance;
            this.theta = (float) theta;
        }

        /**
         * Sets the location of this <code>Polar2D</code> to the specified
         * <code>float</code> coordinates.
         * 
         * @param distance
         *            The distance to which to set this <code>Polar2D</code>
         * @param theta
         *            The theta angle in radians to which to set this
         *            <code>Polar2D</code>
         * @since 1.7
         */
        public void setLocation(float distance, float theta) {
            this.distance = distance;
            this.theta = theta;
        }

        /**
         * Returns a <code>String</code> that represents the value of this
         * <code>Polar2D</code>.
         * 
         * @return A <code>String</code> representation of this
         *         <code>Polar2D</code>.
         * @since 1.7
         */
        @Override
        public String toString() {
            return "Polar2D.Float[" + distance + ", " + theta + "]";
        }
    }

    /**
     * The <code>Double</code> class defines a point specified in
     * <code>double</code> precision.
     */
    public static class Double extends Polar2D {
        /**
         * The distance of this <code>Polar2D</code>.
         * 
         * @since 1.7
         */
        public double distance;
        /**
         * The theta angle in radians of this <code>Polar2D</code>.
         * 
         * @since 1.7
         */
        public double theta;

        /**
         * Constructs and initializes a <code>Polar2D</code> with (0,&nbsp;0)
         * distance and theta angle in radians.
         * 
         * @since 1.7
         */
        public Double() {
        }

        /**
         * Constructs and initializes a <code>Polar2D</code> with the specified
         * coordinates.
         * 
         * @param distance
         *            The distance to which to set the newly constructed
         *            <code>Polar2D</code>
         * @param theta
         *            The theta angle in radians to which to set the newly
         *            constructed <code>Polar2D</code>
         * @since 1.7
         */
        public Double(double distance, double theta) {
            this.distance = distance;
            this.theta = theta;
        }

        /**
         * Returns the distance of this <code>Polar2D</code> in
         * <code>double</code> precision.
         * 
         * @return The distance of this <code>Polar2D</code>.
         * @since 1.7
         */
        @Override
        public double getDistance() {
            return distance;
        }

        /**
         * Returns the theta angle in radians of this <code>Polar2D</code> in
         * <code>double</code> precision.
         * 
         * @return The theta angle in radians of this <code>Polar2D</code>.
         * @since 1.7
         */
        @Override
        public double getTheta() {
            return theta;
        }

        /**
         * Returns the theta angle in degrees of this <code>Polar2D</code> in
         * <code>double</code> precision.
         * 
         * @return The theta angle in degrees of this <code>Polar2D</code>.
         * @since 1.7
         */
        @Override
        public double getThetaInDegrees() {
            double degrees = 180D / Math.PI * theta;
            return (degrees < 0D) ? degrees + 360D : degrees;
        }

        /**
         * Sets the location of this <code>Polar2D</code> to the specified
         * <code>double</code> coordinates.
         * 
         * @param distance
         *            The distance to which to set this <code>Polar2D</code>
         * @param theta
         *            The theta angle in radians to which to set this
         *            <code>Polar2D</code>
         * @since 1.7
         */
        @Override
        public void setLocation(double distance, double theta) {
            this.distance = distance;
            this.theta = theta;
        }

        /**
         * Returns a <code>String</code> that represents the value of this
         * <code>Polar2D</code>.
         * 
         * @return A <code>String</code> representation of this
         *         <code>Polar2D</code>.
         * @since 1.7
         */
        @Override
        public String toString() {
            return "Polar2D.Double[" + distance + ", " + theta + "]";
        }
    }

    /**
     * This is an abstract class that cannot be instantiated directly.
     * Type-specific implementation subclasses are available for instantiation
     * and provide a number of formats for storing the information necessary to
     * satisfy the various accessor methods below.
     * 
     * @see java.awt.geom.Polar2D.Float
     * @see java.awt.geom.Polar2D.Double
     * @see java.awt.Point
     */
    protected Polar2D() {
    }

    /**
     * Returns the distance of this <code>Polar2D</code> in <code>double</code>
     * precision.
     * 
     * @return The distance of this <code>Polar2D</code>.
     * @since 1.7
     */
    public abstract double getDistance();

    /**
     * Returns the theta angle in radians of this <code>Polar2D</code> in
     * <code>double</code> precision.
     * 
     * @return The theta angle in radians of this <code>Polar2D</code>.
     * @since 1.7
     */
    public abstract double getTheta();

    /**
     * Returns the theta angle in degrees of this <code>Polar2D</code> in
     * <code>double</code> precision.
     * 
     * @return The theta angle in degrees of this <code>Polar2D</code>.
     * @since 1.7
     */
    public abstract double getThetaInDegrees();

    /**
     * Sets the location of this <code>Polar2D</code> to the specified
     * <code>double</code> coordinates.
     * 
     * @param distance
     *            The distance of this <code>Polar2D</code>
     * @param theta
     *            The theta angle in radians of this <code>Polar2D</code>
     * @since 1.7
     */
    public abstract void setLocation(double distance, double theta);

    /**
     * Sets the location of this <code>Polar2D</code> to the same coordinates as
     * the specified <code>Polar2D</code> object.
     * 
     * @param p
     *            the specified <code>Polar2D</code> the which to set this
     *            <code>Polar2D</code>
     * @since 1.7
     */
    public void setLocation(Polar2D p) {
        setLocation(p.getDistance(), p.getTheta());
    }

    /**
     * Returns the square of the distance between two points.
     * 
     * @param distance1
     *            The distance of the first point
     * @Parm theta1 The theta angle in radians of the first point
     * @param distance2
     *            The distance of the second point
     * @param theta2
     *            The theta angle in radians of the second point
     * @return The square of the distance between the two specified points.
     */
    public static double distanceSq(double distance1, double theta1,
            double distance2, double theta2) {
        double x1 = distance1 * Math.cos(theta1);
        double y1 = distance1 * Math.sin(theta1);
        double x2 = distance2 * Math.cos(theta2);
        double y2 = distance2 * Math.sin(theta2);
        return (x1 * x2 + y1 * y2);
    }

    /**
     * Returns the distance between two points.
     * 
     * @param distance1
     *            The distance of the first point
     * @param theta1
     *            The theta angle in radians of the first point
     * @param distance2
     *            The distance of the second point
     * @param theta2
     *            The theta angle in radians of the second point
     * @return The distance between the two specified points.
     */
    public static double distance(double distance1, double theta1,
            double distance2, double theta2) {
        double x1 = distance1 * Math.cos(theta1);
        double y1 = distance1 * Math.sin(theta1);
        double x2 = distance2 * Math.cos(theta2);
        double y2 = distance2 * Math.sin(theta2);
        return Math.sqrt(x1 * x2 + y1 * y2);
    }

    /**
     * Returns the square of the distance from this <code>Polar2D</code> to a
     * specified point.
     * 
     * @param distance
     *            The distance of the specified point
     * @param theta
     *            The theta angle in radians of the specified point
     * @return The square of the distance between this <code>Polar2D</code> and
     *         the specified point.
     */
    public double distanceSq(double distance, double theta) {
        double x1 = distance * Math.cos(theta);
        double y1 = distance * Math.sin(theta);
        double x2 = getDistance() * Math.cos(getTheta());
        double y2 = getDistance() * Math.sin(getTheta());
        return (x1 * x2 + y1 * y2);
    }

    /**
     * Returns the square of the distance from this <code>Polar2D</code> to a
     * specified <code>Polar2D</code>.
     * 
     * @param pt
     *            The specified <code>Polar2D</code>
     * @return The square of the distance between this <code>Polar2D</code> to a
     *         specified <code>Polar2D</code>.
     */
    public double distanceSq(Polar2D pt) {
        double x1 = pt.getDistance() * Math.cos(pt.getTheta());
        double y1 = pt.getDistance() * Math.sin(pt.getTheta());
        double x2 = getDistance() * Math.cos(getTheta());
        double y2 = getDistance() * Math.sin(getTheta());
        return (x1 * x2 + y1 * y2);
    }

    /**
     * Returns the distance from this <code>Polar2D</code> to a specified point.
     * 
     * @param distance
     *            The distance of the specified point
     * @param theta
     *            The theta angle in radians of the specified point
     * @return The distance between this <code>Polar2D</code> and a specified
     *         point.
     */
    public double distance(double distance, double theta) {
        double x1 = distance * Math.cos(theta);
        double y1 = distance * Math.sin(theta);
        double x2 = getDistance() * Math.cos(getTheta());
        double y2 = getDistance() * Math.sin(getTheta());
        return Math.sqrt(x1 * x2 + y1 * y2);
    }

    /**
     * Returns the distance from this <code>Polar2D</code> to a specified
     * <code>Polar2D</code>.
     * 
     * @param pt
     *            the specified <code>Polar2D</code>
     * @return The distance between this <code>Polar2D</code> and the specified
     *         <code>Polar2D</code>.
     */
    public double distance(Polar2D pt) {
        double x1 = pt.getDistance() * Math.cos(pt.getTheta());
        double y1 = pt.getDistance() * Math.sin(pt.getTheta());
        double x2 = getDistance() * Math.cos(getTheta());
        double y2 = getDistance() * Math.sin(getTheta());
        return Math.sqrt(x1 * x2 + y1 * y2);
    }

    /**
     * Creates a new object of the same class and with the same contents as this
     * object.
     * 
     * @return a clone of this instance.
     * @exception OutOfMemoryError
     *                if there is not enough memory.
     * @see java.lang.Cloneable
     * @since 1.7
     */
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    }

    /**
     * Returns the hash code for this <code>Polar2D</code>.
     * 
     * @return a hash code for this <code>Polar2D</code>.
     */
    @Override
    public int hashCode() {
        long bits = java.lang.Double.doubleToLongBits(getDistance());
        bits ^= java.lang.Double.doubleToLongBits(getTheta()) * 31;
        return (((int) bits) ^ ((int) (bits >> 32)));
    }

    /**
     * Determines whether or not two points are equal. Two instances of
     * <code>Polar2D</code> are equal if the values of their <code>x</code> and
     * <code>y</code> member fields, representing their position in the
     * coordinate space, are the same.
     * 
     * @param obj
     *            an object to be compared with this <code>Polar2D</code>
     * @return <code>true</code> if the object to be compared is an instance of
     *         <code>Polar2D</code> and has the same values; <code>false</code>
     *         otherwise.
     * @since 1.7
     */
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Polar2D) {
            Polar2D p2d = (Polar2D) obj;
            return (getDistance() == p2d.getDistance())
                    && (getTheta() == p2d.getTheta());
        }
        return super.equals(obj);
    }
}

继续另一个答案。

答案 1 :(得分:0)

接下来是答案的第一部分,因为答案上有30,000个字符限制。

这是在答案的第一部分中测试两个类的一些代码。

CoordinateSystemTester类

package com.ggl.game.utilities.swing;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import com.ggl.game.utilities.CoordinateSystem;
import com.ggl.game.utilities.Polar2D;

public class CoordinateSystemTester implements Runnable {

    private DrawingPanel drawingPanel;

    private JFrame frame;

    @Override
    public void run() {
        frame = new JFrame("Coordinate System Tester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());

        drawingPanel = new DrawingPanel(640, 480);
        mainPanel.add(drawingPanel);

        frame.add(mainPanel);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CoordinateSystemTester());
    }

    private class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1519119839534910933L;

        private CoordinateSystem coordinateSystem;

        private Point pixelPoint;

        private Point2D coordinatePoint;

        private String coordinateString;

        public DrawingPanel(int width, int height) {
            this.coordinateSystem = new CoordinateSystem(25.0D, width, height);
            this.coordinatePoint = new Point2D.Double();
            this.pixelPoint = new Point();
            this.coordinateString = "";

            addComponentListener(new SizeListener());
            addMouseListener(new CoordinateListener());
            setPreferredSize(new Dimension(width, height));
        }

        public CoordinateSystem getCoordinateSystem() {
            return coordinateSystem;
        }

        public Point2D getCoordinatePoint() {
            return coordinatePoint;
        }

        public void setCoordinatePoint(Point2D coordinatePoint) {
            this.coordinatePoint = coordinatePoint;
        }

        public Point getPixelPoint() {
            return pixelPoint;
        }

        public void setPixelPoint(Point pixelPoint) {
            this.pixelPoint = pixelPoint;
        }

        public void setCoordinateString(String coordinateString) {
            this.coordinateString = coordinateString;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, getWidth(), getHeight());

            g2d.setColor(Color.BLACK);
            g2d.drawString(createLimitsString(), 10, 20);

            drawXAxis(g2d, g);
            drawYAxis(g2d, g);
            drawCoordinate(g2d, g);
        }

        private String createLimitsString() {
            String xs = String.format("%.2f", coordinateSystem.getxLimit());
            String ys = String.format("%.2f", coordinateSystem.getyLimit());

            StringBuilder builder = new StringBuilder();
            builder.append("The actual limits are (");
            builder.append(xs);
            builder.append(", ");
            builder.append(ys);
            builder.append(")");

            return builder.toString();
        }

        private void drawXAxis(Graphics2D g2d, Graphics g) {
            g2d.setColor(Color.BLACK);
            g2d.setStroke(new BasicStroke(5.0F));
            Point p1 = coordinateSystem.convertPointToPixels(-20.0D, 0.0D);
            Point p2 = coordinateSystem.convertPointToPixels(20.0D, 0.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);

            g2d.setStroke(new BasicStroke(3.0F));
            p1 = coordinateSystem.convertPointToPixels(-20.0D, -1.0D);
            p2 = coordinateSystem.convertPointToPixels(-20.0D, 1.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);

            Font font = getFont();
            Point p3 = coordinateSystem.convertPointToPixels(-20.0D, -1.0D);
            Rectangle r = new Rectangle(p3.x - 20, p3.y, 40, 20);
            centerString(g, r, "-20.0", font);

            p1 = coordinateSystem.convertPointToPixels(-10.0D, -1.0D);
            p2 = coordinateSystem.convertPointToPixels(-10.0D, 1.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
            p3 = coordinateSystem.convertPointToPixels(-10.0D, -1.0D);
            r = new Rectangle(p3.x - 20, p3.y, 40, 20);
            centerString(g, r, "-10.0", font);

            p1 = coordinateSystem.convertPointToPixels(10.0D, -1.0D);
            p2 = coordinateSystem.convertPointToPixels(10.0D, 1.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
            p3 = coordinateSystem.convertPointToPixels(10.0D, -1.0D);
            r = new Rectangle(p3.x - 20, p3.y, 40, 20);
            centerString(g, r, "10.0", font);

            p1 = coordinateSystem.convertPointToPixels(20.0D, -1.0D);
            p2 = coordinateSystem.convertPointToPixels(20.0D, 1.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
            p3 = coordinateSystem.convertPointToPixels(20.0D, -1.0D);
            r = new Rectangle(p3.x - 20, p3.y, 40, 20);
            centerString(g, r, "20.0", font);
        }

        private void drawYAxis(Graphics2D g2d, Graphics g) {
            g2d.setColor(Color.BLACK);
            g2d.setStroke(new BasicStroke(5.0F));
            Point p1 = coordinateSystem.convertPointToPixels(0.0D, -20.0D);
            Point p2 = coordinateSystem.convertPointToPixels(0.0D, 20.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);

            g2d.setStroke(new BasicStroke(3.0F));
            p1 = coordinateSystem.convertPointToPixels(-1.0D, -20.0D);
            p2 = coordinateSystem.convertPointToPixels(1.0D, -20.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);

            Font font = getFont();
            Point p3 = coordinateSystem.convertPointToPixels(3.0D, -20.0D);
            Rectangle r = new Rectangle(p3.x - 20, p3.y, 40, 20);
            centerString(g, r, "-20.0", font);

            p1 = coordinateSystem.convertPointToPixels(-1.0D, -10.0D);
            p2 = coordinateSystem.convertPointToPixels(1.0D, -10.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
            p3 = coordinateSystem.convertPointToPixels(3.0D, -10.0D);
            r = new Rectangle(p3.x - 20, p3.y, 40, 20);
            centerString(g, r, "-10.0", font);

            p1 = coordinateSystem.convertPointToPixels(-1.0D, 10.0D);
            p2 = coordinateSystem.convertPointToPixels(1.0D, 10.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
            p3 = coordinateSystem.convertPointToPixels(3.0D, 10.0D);
            r = new Rectangle(p3.x - 20, p3.y, 40, 20);
            centerString(g, r, "10.0", font);

            p1 = coordinateSystem.convertPointToPixels(-1.0D, 20.0D);
            p2 = coordinateSystem.convertPointToPixels(1.0D, 20.0D);
            g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
            p3 = coordinateSystem.convertPointToPixels(3.0D, 20.0D);
            r = new Rectangle(p3.x - 20, p3.y, 40, 20);
            centerString(g, r, "20.0", font);
        }

        private void drawCoordinate(Graphics2D g2d, Graphics g) {
            if (!coordinateString.equals("")) {
                g2d.setColor(Color.BLUE);
                g2d.fillOval(pixelPoint.x - 5, pixelPoint.y - 5, 10, 10);
                Font font = getFont();
                Rectangle r = new Rectangle(pixelPoint.x - 30, pixelPoint.y,
                        60, 20);
                centerString(g, r, coordinateString, font);
            }
        }

        /**
         * This method centers a <code>String</code> in a bounding
         * <code>Rectangle</code>.
         * 
         * @param g
         *            - The <code>Graphics</code> instance.
         * @param r
         *            - The bounding <code>Rectangle</code>.
         * @param s
         *            - The <code>String</code> to center in the bounding
         *            rectangle.
         * @param font
         *            - The display font of the <code>String</code>
         * 
         * @see java.awt.Graphics
         * @see java.awt.Rectangle
         * @see java.lang.String
         */
        private void centerString(Graphics g, Rectangle r, String s, Font font) {
            FontRenderContext frc = new FontRenderContext(null, true, true);

            Rectangle2D r2D = font.getStringBounds(s, frc);
            int rWidth = (int) Math.round(r2D.getWidth());
            int rHeight = (int) Math.round(r2D.getHeight());
            int rX = (int) Math.round(r2D.getX());
            int rY = (int) Math.round(r2D.getY());

            int a = (r.width / 2) - (rWidth / 2) - rX;
            int b = (r.height / 2) - (rHeight / 2) - rY;

            g.setFont(font);
            g.drawString(s, r.x + a, r.y + b);
        }
    }

    private class CoordinateListener extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent event) {
            drawingPanel.setPixelPoint(event.getPoint());
            Point2D coordinatePoint = drawingPanel.getCoordinateSystem()
                    .convertToCartesian(event.getPoint());
            drawingPanel.setCoordinatePoint(coordinatePoint);

            StringBuilder builder = new StringBuilder();

            if (event.getButton() == MouseEvent.BUTTON1) {
                builder.append("(");
                builder.append(String.format("%.2f", coordinatePoint.getX()));
                builder.append(", ");
                builder.append(String.format("%.2f", coordinatePoint.getY()));
                builder.append(")");
            } else if (event.getButton() == MouseEvent.BUTTON3) {
                Polar2D polarPoint = drawingPanel.getCoordinateSystem()
                        .convertToPolar(event.getPoint());

                builder.append("(");
                builder.append(String.format("%.2f", polarPoint.getDistance()));
                builder.append(", ");
                builder.append(String.format("%.2f",
                        polarPoint.getThetaInDegrees()));
                builder.append(")");
            }

            drawingPanel.setCoordinateString(builder.toString());
            drawingPanel.repaint();
        }

    }

    private class SizeListener extends ComponentAdapter {

        @Override
        public void componentResized(ComponentEvent event) {
            Dimension d = drawingPanel.getSize();
            drawingPanel.getCoordinateSystem().setDrawingSize(d);
            if (!drawingPanel.getPixelPoint().equals(new Point())) {
                Point2D p2d = drawingPanel.getCoordinatePoint();
                Point p = drawingPanel.getCoordinateSystem().convertToPixels(
                        p2d);
                drawingPanel.setPixelPoint(p);
            }
            drawingPanel.repaint();
        }
    }

}