From 35942ebfce3fd0a57ea1310dc7d7c4568ac5405d Mon Sep 17 00:00:00 2001 From: bjculkin Date: Wed, 11 Apr 2018 15:18:40 -0400 Subject: Documenting --- CSMath/src/CulkinAsssignmentNine.java | 706 +++++++++++++++++++++++++++++++--- 1 file changed, 657 insertions(+), 49 deletions(-) (limited to 'CSMath/src/CulkinAsssignmentNine.java') diff --git a/CSMath/src/CulkinAsssignmentNine.java b/CSMath/src/CulkinAsssignmentNine.java index 4626cc8..bc81796 100644 --- a/CSMath/src/CulkinAsssignmentNine.java +++ b/CSMath/src/CulkinAsssignmentNine.java @@ -8,7 +8,6 @@ import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; @@ -20,6 +19,7 @@ import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JColorChooser; +import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFormattedTextField; import javax.swing.JFrame; @@ -49,6 +49,7 @@ public class CulkinAsssignmentNine { * The current bezier curve. */ public final Holder currentCurve; + /** * The directory of all bezier curves. */ @@ -75,6 +76,9 @@ public class CulkinAsssignmentNine { public static void main(String[] args) { CulkinAsssignmentNine assign = new CulkinAsssignmentNine(); + /* + * Use the native look and feel. + */ try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException @@ -84,11 +88,17 @@ public class CulkinAsssignmentNine { JFrame fram = assign.setupFrame(); + /* + * Display the GUI. + */ fram.setSize(640, 480); fram.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); fram.setVisible(true); } + /* + * Setup the main JFrame + */ private JFrame setupFrame() { JFrame fram = new JFrame("Bezier Grapher"); fram.setLayout(new BorderLayout()); @@ -107,8 +117,15 @@ public class CulkinAsssignmentNine { listPanel.setLayout(new GridLayout(1, 1)); DefaultListModel pointModel = new DefaultListModel<>(); + + /* + * Repaint the canvas whenever the list changes. + */ pointModel.addListDataListener(new CanvasRepainter(canvas)); + /* + * Update the list whenever the curve changes. + */ currentCurve.addHolderListener((val) -> { pointModel.clear(); @@ -118,6 +135,10 @@ public class CulkinAsssignmentNine { }); JList pointList = new JList<>(pointModel); + + /* + * Use special point renderer. + */ pointList.setCellRenderer(new TDPointRenderer()); JScrollPane listScroller = new JScrollPane(pointList); @@ -127,6 +148,9 @@ public class CulkinAsssignmentNine { JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new GridLayout(1, 2)); + /* + * Setup action buttons. + */ JButton addPoint = new JButton("Add Control Points..."); addPoint.addActionListener(new PointAdder(pointModel, currentCurve, fram)); @@ -157,6 +181,9 @@ public class CulkinAsssignmentNine { destructivePanel.setLayout(new FlowLayout(FlowLayout.LEADING, 5, 1)); destructivePanel.setBorder(new BevelBorder(BevelBorder.RAISED)); + /* + * Clear all curve points. + */ JButton clearPoints = new JButton("Clear Points"); clearPoints.addActionListener((ev) -> { int confirm = JOptionPane.showConfirmDialog(fram, "Are you sure you want to clear the points?", @@ -168,6 +195,9 @@ public class CulkinAsssignmentNine { } }); + /* + * Reset to use new curve. + */ JButton resetCurve = new JButton("Reset Curve"); resetCurve.addActionListener((ev) -> { int confirm = JOptionPane.showConfirmDialog(fram, "Are you sure you want to reset the curve?", @@ -175,9 +205,11 @@ public class CulkinAsssignmentNine { if (confirm == JOptionPane.YES_OPTION) { currentCurve.getVal().controls.clear(); - + currentCurve.setVal(new Bezier()); - + + curveDirectory.put("Default", currentCurve.getVal()); + canvas.repaint(); } }); @@ -185,13 +217,16 @@ public class CulkinAsssignmentNine { destructivePanel.add(clearPoints); destructivePanel.add(resetCurve); + /* + * This isn't implemented yet. + */ JPanel curvesPanel = new JPanel(); curvesPanel.setLayout(new FlowLayout(FlowLayout.LEADING, 5, 1)); curvesPanel.setBorder(new BevelBorder(BevelBorder.RAISED)); menuPanel.add(editingPanel); menuPanel.add(destructivePanel); - menuPanel.add(curvesPanel); + // menuPanel.add(curvesPanel); fram.add(main, BorderLayout.CENTER); fram.add(menuPanel, BorderLayout.PAGE_START); @@ -200,6 +235,9 @@ public class CulkinAsssignmentNine { } } +/* + * Do editing of curve properties. + */ class CurveEditor implements ActionListener { private Bezier curve; private JFrame fram; @@ -211,6 +249,9 @@ class CurveEditor implements ActionListener { curve = currentCurve.getVal(); + /* + * Set the curve to the right one. + */ currentCurve.addHolderListener((val) -> { curve = val; }); @@ -224,20 +265,20 @@ class CurveEditor implements ActionListener { JPanel fields = new JPanel(); fields.setLayout(new BorderLayout()); - LabeledInputPanel partsPanel = new LabeledInputPanel("# of Points to Graph", curve.parts); + LabeledInputPanel partsPanel = new LabeledInputPanel("# of Points to Graph", curve.data.parts); JTabbedPane colorPanel = new JTabbedPane(); colorPanel.setBorder(new TitledBorder(new BevelBorder(BevelBorder.RAISED), "Colors")); - ColorInputPanel curveColor = new ColorInputPanel(curve.curveColor, "Curve Color"); - ColorInputPanel pointColor = new ColorInputPanel(curve.pointColor, "Point Color"); - ColorInputPanel boxColor = new ColorInputPanel(curve.boxColor, "Bounding Box Color"); + ColorInputPanel curveColor = new ColorInputPanel(curve.data.curveColor, "Curve Color"); + ColorInputPanel pointColor = new ColorInputPanel(curve.data.pointColor, "Point Color"); + ColorInputPanel boxColor = new ColorInputPanel(curve.data.boxColor, "Bounding Box Color"); colorPanel.addTab("Curve Color", curveColor); colorPanel.addTab("Point Color", pointColor); colorPanel.addTab("Bounding Box Color", boxColor); - LabeledInputPanel scalePanel = new LabeledInputPanel("Curve Scaling Multiplier", curve.scale); + LabeledInputPanel scalePanel = new LabeledInputPanel("Curve Scaling Multiplier", curve.data.scale); fields.add(partsPanel, BorderLayout.PAGE_START); fields.add(colorPanel, BorderLayout.CENTER); @@ -246,26 +287,32 @@ class CurveEditor implements ActionListener { JPanel buttons = new JPanel(); buttons.setLayout(new GridLayout(1, 3)); + /* + * Persist changes to curve. + */ JButton saveButton = new JButton("Save Changes"); saveButton.addActionListener((aev) -> { - curve.parts = (Integer) partsPanel.field.getValue(); - curve.scale = (Double) scalePanel.field.getValue(); + curve.data.parts = (Integer) partsPanel.field.getValue(); + curve.data.scale = (Double) scalePanel.field.getValue(); - curve.curveColor = curveColor.picker.getColor(); - curve.pointColor = pointColor.picker.getColor(); - curve.boxColor = boxColor.picker.getColor(); + curve.data.curveColor = curveColor.picker.getColor(); + curve.data.pointColor = pointColor.picker.getColor(); + curve.data.boxColor = boxColor.picker.getColor(); canvas.repaint(); }); + /* + * Reset fields to match curve. + */ JButton resetButton = new JButton("Reset Changes"); resetButton.addActionListener((aev) -> { - partsPanel.field.setValue(curve.parts); - scalePanel.field.setValue(curve.scale); + partsPanel.field.setValue(curve.data.parts); + scalePanel.field.setValue(curve.data.scale); - curveColor.picker.setColor(curve.curveColor); - pointColor.picker.setColor(curve.pointColor); - boxColor.picker.setColor(curve.boxColor); + curveColor.picker.setColor(curve.data.curveColor); + pointColor.picker.setColor(curve.data.pointColor); + boxColor.picker.setColor(curve.data.boxColor); }); JButton cancelButton = new JButton("Cancel Changes"); @@ -285,6 +332,9 @@ class CurveEditor implements ActionListener { } } +/* + * Panel for inputting colors. + */ class ColorInputPanel extends JPanel { private static final long serialVersionUID = 5201595672794938745L; @@ -306,6 +356,9 @@ class ColorInputPanel extends JPanel { } } +/* + * Panel that graphs a set of bezier curves. + */ class BezierPanel extends JPanel { public final Collection curves; @@ -339,22 +392,37 @@ class BezierPanel extends JPanel { g.setColor(Color.WHITE); + /* + * Draw background + */ g.fillRect(0, 0, ourWidth, ourHeight); g.setColor(Color.BLUE); + /* + * Draw coordinate grid. + */ g.drawLine(halfWidth, 0, halfWidth, ourHeight); g.drawLine(0, halfHeight, ourWidth, halfHeight); + /* + * Transform to place points at center of grid w/ right orientation. + */ TDHTransform translate = new TDHCombination(new TDHXAxisReflection(), new TDHTranslate(halfWidth, halfHeight)); for (Bezier curve : curves) { + /* + * Skip curves with no points. + */ if (curve.controls.isEmpty()) { continue; } { - g.setColor(curve.boxColor); + /* + * Draw curve bounding box. + */ + g.setColor(curve.data.boxColor); TDPoint[] ex = curve.extrema(translate); g.drawLine((int) ex[0].x, (int) ex[0].y, (int) ex[1].x, (int) ex[1].y); @@ -363,18 +431,24 @@ class BezierPanel extends JPanel { g.drawLine((int) ex[3].x, (int) ex[3].y, (int) ex[0].x, (int) ex[0].y); } - g.setColor(curve.pointColor); + g.setColor(curve.data.pointColor); for (TDPoint control : curve.controls) { - TDHPoint translatedPoint = translate.transform(control.multiply(curve.scale).toTDHPoint()); + /* + * Draw curve points. + */ + TDHPoint translatedPoint = translate.transform(control.multiply(curve.data.scale).toTDHPoint()); control = translatedPoint.toTDPoint(); drawCircle(g, control.x, control.y, 6); } - g.setColor(curve.curveColor); - for (int i = 0; i < curve.parts; i++) { - double dT = 1.0 / curve.parts; + g.setColor(curve.data.curveColor); + for (int i = 0; i < curve.data.parts; i++) { + /* + * Draw curve itself. + */ + double dT = 1.0 / curve.data.parts; TDPoint firt = curve.scaleEval(dT * i); TDPoint secod = curve.scaleEval(dT * (i + 1)); @@ -387,22 +461,37 @@ class BezierPanel extends JPanel { } } + /* + * Draw a circle of a given diameter at a point. + */ private static void drawCircle(Graphics g, double x, double y, int diameter) { g.fillOval((int) x - diameter / 2, (int) y - diameter / 2, diameter, diameter); } } +/** + * Represents a bezier curve. + */ class Bezier { + /** + * The control points of the curve. + */ public final List controls; - public int parts = 100; - public double scale = 5; - - public Color curveColor = Color.BLACK; - public Color pointColor = Color.RED; - public Color boxColor = Color.GREEN; + /** + * The display properties for the curve. + */ + public BezierProperties data; + /** + * Create a new bezier curve from a set of control points. + * + * @param points + * The control points to use. + */ public Bezier(TDPoint... points) { + data = new BezierProperties(); + controls = new ArrayList<>(); for (TDPoint punkt : points) { @@ -410,10 +499,23 @@ class Bezier { } } + /** + * Do a scaled evaluation of the curve. + * + * @param t + * The value to evaluate at. + * @return The point on the curve, scaled by the curves scaling factor. + */ public TDPoint scaleEval(double t) { - return eval(t).multiply(scale); + return eval(t).multiply(data.scale); } + /** + * Do a scaled evaluation of the curve. + * + * @param t + * The value to evaluate at. + */ public TDPoint eval(double t) { if (controls.isEmpty()) return new TDPoint(0, 0); @@ -423,24 +525,49 @@ class Bezier { return punkt; } + /* + * Recursive evaluation of bezier curve. + */ private TDPoint evalIntern(double t, int j, int k) { + /* + * Base case. + */ if (j <= 0) { return controls.get(k); } + /* + * Get the two component points. + */ TDPoint l = evalIntern(t, j - 1, k); TDPoint r = evalIntern(t, j - 1, k + 1); + /* + * Adjust them by parameter value + */ l = l.multiply(1 - t); r = r.multiply(t); + /* + * Give back their sum + */ return TDPoint.add(l, r); } + /** + * Split a curve into two curves at a specific point. + * + * @param t + * The point to split the curve at. + * @return The two curves, split at that point. + */ public Bezier[] decompose(double t) { Bezier[] curves = new Bezier[2]; { + /* + * Get the first curve. + */ TDPoint[] points = new TDPoint[controls.size()]; for (int i = 0; i < points.length; i++) { points[i] = evalIntern(t, i, 0); @@ -449,6 +576,9 @@ class Bezier { } { + /* + * Get the second curve. + */ TDPoint[] points = new TDPoint[controls.size()]; for (int i = 0; i < points.length; i++) { points[i] = evalIntern(t, (points.length - 1) - i, i); @@ -459,10 +589,22 @@ class Bezier { return curves; } + /** + * Get the bounding box for this curves control points. + * + * @return The bounding box for the control points. + */ public TDPoint[] extrema() { return extrema(new TDHIdentity()); } + /** + * Get the bounding box for a transformed version of this curves control points. + * + * @param transform + * The transform to apply to the control points. + * @return The bounding box for the transformed control points. + */ public TDPoint[] extrema(TDHTransform transform) { TDPoint[] box = new TDPoint[4]; @@ -470,27 +612,36 @@ class Bezier { double yMin = Double.MAX_VALUE, yMax = Double.MIN_VALUE; for (TDPoint punkt1 : controls) { - TDPoint punkt = punkt1.multiply(scale); - + /* + * Get transformed point + */ + TDPoint punkt = punkt1.multiply(data.scale); punkt = transform.transform(punkt.toTDHPoint()).toTDPoint(); + /* + * Set min/max x vals + */ if (punkt.x < xMin) { xMin = punkt.x; } - if (punkt.x > xMax) { xMax = punkt.x; } + /* + * Set min/max y vals + */ if (punkt.y < yMin) { yMin = punkt.y; } - if (punkt.y > yMax) { yMax = punkt.y; } } + /* + * Create returned points. + */ box[0] = new TDPoint(xMin, yMin); box[1] = new TDPoint(xMax, yMin); box[2] = new TDPoint(xMax, yMax); @@ -530,23 +681,69 @@ class Bezier { } } +/** + * Represents a two-dimensional point. + * + * @author bjculkin + * + */ class TDPoint { + /** + * The x coordinate. + */ public final double x; + + /** + * The y coordinate. + */ public final double y; + /** + * Create a new two-dimensional point. + * + * @param x + * The x coordinate. + * @param y + * The y coordinate. + */ public TDPoint(double x, double y) { this.x = x; this.y = y; } + /** + * Create a new two-dimensional point. + * + * @param x + * The x coordinate. + * @param y + * The y coordinate. + * @return A point with those coordinates. + */ public static TDPoint p2(double x, double y) { return new TDPoint(x, y); } + /** + * Return a new scaled point. + * + * @param s + * The amount to scale by. + * @return A point scaled by the specified amount. + */ public TDPoint multiply(double s) { return p2(x * s, y * s); } + /** + * Add two points together. + * + * @param p1 + * The first point to add. + * @param p2 + * The second point to add. + * @return The sum of the points. + */ public static TDPoint add(TDPoint p1, TDPoint p2) { return p2(p1.x + p2.x, p1.y + p2.y); } @@ -584,21 +781,67 @@ class TDPoint { return "TDPoint [x=" + x + ", y=" + y + "]"; } + /** + * Convert this point to a two-dimensional homogeneous point. + * + * @return A homogeneous version of this point. + */ public TDHPoint toTDHPoint() { - return new TDHPoint(x, y, 1); + return new TDHPoint(x, y); } } +/** + * A two-dimensional homogeneous point. + * + * @author bjculkin + * + */ class TDHPoint extends TDPoint { + /** + * The homogeneous coordinate for the point. + */ public final double z; + /** + * Create a new two-dimensional homogeneous point. + * + * @param x + * The x coordinate. + * @param y + * The y coordinate. + * @param z + * The homogeneous coordinate. + */ public TDHPoint(double x, double y, double z) { super(x, y); this.z = z; } + /** + * Create a new two-dimensional homogeneous point. + * + * The homogeneous coordinate is set to 1. + * + * @param x + * The x coordinate. + * @param y + * The y coordinate. + */ + public TDHPoint(double x, double y) { + this(x, y, 1); + } + + /** + * Convert this point to a plain two-dimensional point. + * + * @return A two-dimensional version of this point. + */ public TDPoint toTDPoint() { + /* + * Convert back down by dividing each coordinate by the homogeneous value. + */ return new TDPoint(x / z, y / z); } @@ -628,13 +871,22 @@ class TDHPoint extends TDPoint { @Override public String toString() { - return "TDHPoint [z=" + z + "]"; + return "TDHPoint [z=" + z + ", x=" + x + ", y=" + y + "]"; } } +/** + * Renderer for TDPoints in JLists. + * + * @author bjculkin + * + */ final class TDPointRenderer extends JLabel implements ListCellRenderer { private static final long serialVersionUID = 629873168260730449L; + /** + * Create a new TDPoint renderer. + */ public TDPointRenderer() { setOpaque(true); setHorizontalAlignment(CENTER); @@ -658,6 +910,12 @@ final class TDPointRenderer extends JLabel implements ListCellRenderer } } +/** + * Listener to remove points from a bezier curve. + * + * @author bjculkin + * + */ class PointRemover implements ActionListener { private final JFrame fram; private final JList pointList; @@ -665,12 +923,27 @@ class PointRemover implements ActionListener { private Bezier curve; + /** + * Create a new listener to remove points from a bezier curve. + * + * @param fram + * The frame to use. + * @param pointList + * The list the points are stored in. + * @param pointModel + * The data backing the list. + * @param curveHolder + * The current curve. + */ public PointRemover(JFrame fram, JList pointList, DefaultListModel pointModel, Holder curveHolder) { this.fram = fram; this.pointList = pointList; this.pointModel = pointModel; + /* + * Change our curve if the current one changes. + */ curve = curveHolder.getVal(); curveHolder.addHolderListener((val) -> { curve = val; @@ -680,12 +953,13 @@ class PointRemover implements ActionListener { @Override public void actionPerformed(ActionEvent ev) { int selectedIndex = pointList.getSelectedIndex(); - + /* * Nothing selected. */ - if(selectedIndex == -1) return; - + if (selectedIndex == -1) + return; + TDPoint punkt = pointModel.get(selectedIndex); String msg = String.format("Do you want to remove the control point (%.2f, %.2f)?", punkt.x, punkt.y); @@ -699,17 +973,36 @@ class PointRemover implements ActionListener { } } +/** + * Listener for adding points to a bezier curve. + * + * @author bjculkin + * + */ class PointAdder implements ActionListener { private final DefaultListModel pointModel; private final JFrame fram; private Bezier curve; + /** + * Create a listener that adds points to a bezier curve. + * + * @param pointModel + * The place to store points. + * @param curveHolder + * The curve to add to. + * @param fram + * The frame to use. + */ public PointAdder(DefaultListModel pointModel, Holder curveHolder, JFrame fram) { this.pointModel = pointModel; this.curve = curveHolder.getVal(); this.fram = fram; + /* + * Change our curve if the current one changes. + */ curveHolder.addHolderListener((curv) -> { curve = curv; }); @@ -747,10 +1040,12 @@ class PointAdder implements ActionListener { buttons.add(add); buttons.add(cancel); + /* + * Change focus to each field on action + */ xPanel.field.addActionListener((aev) -> { yPanel.field.requestFocusInWindow(); }); - yPanel.field.addActionListener((aev) -> { addListener.actionPerformed(null); }); @@ -762,6 +1057,12 @@ class PointAdder implements ActionListener { dia.setVisible(true); } + /** + * Listener for adding points to a curve. + * + * @author bjculkin + * + */ class AddListener implements ActionListener { private final LabeledInputPanel xPanel; private final LabeledInputPanel yPanel; @@ -773,6 +1074,9 @@ class PointAdder implements ActionListener { @Override public void actionPerformed(ActionEvent aev) { + /* + * Add point to curve. + */ double xVal = (Double) xPanel.field.getValue(); double yVal = (Double) yPanel.field.getValue(); @@ -781,6 +1085,9 @@ class PointAdder implements ActionListener { pointModel.addElement(punkt); curve.controls.add(punkt); + /* + * Reset field values. + */ xPanel.field.setValue(0.0); yPanel.field.setValue(0.0); @@ -789,34 +1096,63 @@ class PointAdder implements ActionListener { } } +/** + * Listener to repaint a component whenever a list changes. + * + * @author bjculkin + * + */ class CanvasRepainter implements ListDataListener { - private final BezierPanel canvas; + private final JComponent comp; - public CanvasRepainter(BezierPanel canvas) { - this.canvas = canvas; + /** + * Create a new repaint listener. + * + * @param canvas + * The component to repaint. + */ + public CanvasRepainter(JComponent canvas) { + this.comp = canvas; } @Override public void intervalRemoved(ListDataEvent e) { - canvas.repaint(); + comp.repaint(); } @Override public void intervalAdded(ListDataEvent e) { - canvas.repaint(); + comp.repaint(); } @Override public void contentsChanged(ListDataEvent e) { - canvas.repaint(); + comp.repaint(); } } +/** + * A component for getting formatted input with a label. + * + * @author bjculkin + * + */ class LabeledInputPanel extends JPanel { private static final long serialVersionUID = 1031310890698539040L; + /** + * The field input is stored in. + */ public final JFormattedTextField field; + /** + * Create a new labeled input component. + * + * @param label + * The label for the component. + * @param val + * The initial value for the field. + */ public LabeledInputPanel(String label, Object val) { super(); setLayout(new BorderLayout()); @@ -830,33 +1166,78 @@ class LabeledInputPanel extends JPanel { } } +/** + * Dummy class for holding a value, and being notified when it changes. + * + * Essentially a pointer with change notifications. + * + * @author bjculkin + * + * @param + * The type of held value. + */ class Holder { + /* + * The held value. + */ private E val; + /* + * The listeners to notify. + */ private final List> listeners; + /** + * Create a new holder holding nothing. + */ public Holder() { listeners = new LinkedList<>(); } + /** + * Create a new holder holding a specific value. + * + * @param val + * The value being held. + */ public Holder(E val) { this(); this.val = val; } + /** + * Get the contained value. + * + * @return The contained value. + */ public E getVal() { return val; } + /** + * Set the contained value, and notify listeners. + * + * @param val + * The new value. + */ public void setVal(E val) { this.val = val; + /* + * Notify listeners. + */ for (Consumer listen : listeners) { listen.accept(val); } } + /** + * Add a listener. + * + * @param listen + * The listener to add. + */ public void addHolderListener(Consumer listen) { listeners.add(listen); } @@ -892,27 +1273,104 @@ class Holder { } } +/** + * Types of transform to apply to TDHPoints. + * + * @author bjculkin + * + */ enum TDHTransformType { - TRANSLATE, IDENTITY, SCALE, ROTATION, REFLECTION, SHEAR, COMBINATION, MATRIX + /** + * Coordinate translation. + */ + TRANSLATE, + /** + * Do nothing transform. + */ + IDENTITY, + /** + * Coordinate scaling. + */ + SCALE, + /** + * Coordinate rotation. + */ + ROTATION, + /** + * Coordinate reflection. + */ + REFLECTION, + /** + * Coordinate shearing. + */ + SHEAR, + /** + * Multiple transformations. + */ + COMBINATION, + /** + * Arbitrary matrix transformation. + */ + MATRIX } +/** + * Transformation applicable to TDHPoints. + * + * @author bjculkin + * + */ @FunctionalInterface interface TDHTransform { + /** + * Get the type of this transform. + * + * Unknown transformations are assumed to be identity transforms. + * + * @return The type of this transform. + */ default TDHTransformType type() { return TDHTransformType.IDENTITY; } + /** + * Get the matrix representation of the transform. + * + * Unknown transformations are assumed to be identity transforms. + * + * @return The matrix representation of the transform. + */ default double[][] matrix() { return new double[][] { new double[] { 1, 0, 0 }, new double[] { 0, 1, 0 }, new double[] { 0, 0, 1 } }; } + /** + * Get the inverse of the transform. + * + * Unknown transformations are assumed to be identity transforms. + * + * @return The inverse the transform. + */ default TDHTransform invert() { return new TDHIdentity(); } + /** + * Apply the transform to a point. + * + * @param punkt + * The point to transform. + * @return A transformed version of the point. + */ TDHPoint transform(TDHPoint punkt); } +/** + * A transform that does nothing. + * + * @author bjculkin + * + */ class TDHIdentity implements TDHTransform { @Override public TDHPoint transform(TDHPoint punkt) { @@ -925,10 +1383,30 @@ class TDHIdentity implements TDHTransform { } } +/** + * A transform that does coordinate translation. + * + * @author bjculkin + * + */ class TDHTranslate implements TDHTransform { + /** + * The amount to translate the x-coordinate by. + */ public final double h; + /** + * The amount to translate the y-coordinate by. + */ public final double k; + /** + * Create a new translation transform. + * + * @param h + * The amount to translate x by. + * @param k + * The amount to translate y by. + */ public TDHTranslate(double h, double k) { this.h = h; this.k = k; @@ -991,11 +1469,60 @@ class TDHTranslate implements TDHTransform { } } +/** + * Transform that does coordinate scaling. + * + * @author bjculkin + * + */ class TDHScale implements TDHTransform { + /** + * Amount to scale x by. + */ public final double sx; + /** + * Amount to scale y by. + */ public final double sy; + /** + * Amount to scale the homogeneous coordinate by. + */ public final double sz; + /** + * Create a new scaling that scales each coordinate by an equal amount + * + * @param factor + * The amount to scale the coordinates by. + */ + public TDHScale(double factor) { + this(factor, factor); + } + + /** + * Create a new scaling that scales each coordinate separately. + * + * @param sx + * The amount to scale x by. + * @param sy + * The amount to scale y by. + */ + public TDHScale(double sx, double sy) { + this(sx, sy, 1); + } + + /** + * Create a new scaling that scales each coordinate separately. + * + * Includes the homogeneous coordinate. + * + * @param sx + * The amount to scale x by. + * @param sy + * The amount to scale y by. + * @param sz + * The amount to scale the homogeneous coordinate by. + */ public TDHScale(double sx, double sy, double sz) { this.sx = sx; this.sy = sy; @@ -1429,4 +1956,85 @@ class TDHCombination implements TDHTransform { public String toString() { return "TDHCombination [forms=" + forms + "]"; } +} + +class BezierProperties { + /** + * The number of separate points to graph from the curve. + */ + public int parts = 100; + + /** + * The multiplier to apply to coordinates. + */ + public double scale = 5; + + /** + * The colors for varying parts of the curve. + */ + public Color curveColor = Color.BLACK; + public Color pointColor = Color.RED; + public Color boxColor = Color.GREEN; + + public BezierProperties() { + } + + public BezierProperties(int parts, double scale, Color curveColor, Color pointColor, Color boxColor) { + this.parts = parts; + this.scale = scale; + this.curveColor = curveColor; + this.pointColor = pointColor; + this.boxColor = boxColor; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((boxColor == null) ? 0 : boxColor.hashCode()); + result = prime * result + ((curveColor == null) ? 0 : curveColor.hashCode()); + result = prime * result + parts; + result = prime * result + ((pointColor == null) ? 0 : pointColor.hashCode()); + long temp; + temp = Double.doubleToLongBits(scale); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BezierProperties other = (BezierProperties) obj; + if (boxColor == null) { + if (other.boxColor != null) + return false; + } else if (!boxColor.equals(other.boxColor)) + return false; + if (curveColor == null) { + if (other.curveColor != null) + return false; + } else if (!curveColor.equals(other.curveColor)) + return false; + if (parts != other.parts) + return false; + if (pointColor == null) { + if (other.pointColor != null) + return false; + } else if (!pointColor.equals(other.pointColor)) + return false; + if (Double.doubleToLongBits(scale) != Double.doubleToLongBits(other.scale)) + return false; + return true; + } + + @Override + public String toString() { + return "BezierProperties [parts=" + parts + ", scale=" + scale + ", curveColor=" + curveColor + ", pointColor=" + + pointColor + ", boxColor=" + boxColor + "]"; + } } \ No newline at end of file -- cgit v1.2.3