public class CubicSubdivision extends DisplayPanel { /** * The paintable sequence variable that will represent * the cubic subdivision structure. * * This sequence will be constructed just before it is * time to paint the cubic subdivision. * * This sequence will be placed in the tile. */ PaintableSequence sequence = null; /** The tile size. */ int size = 600; /** The tile bounds. */ XRect bounds = new XRect(0, 0, size, size); /** The tile to display the cubic structure. */ Tile tile = new Tile(); // The tile initialization. { tile.setDefaultBounds2D(bounds); } /** The paintable component to hold the tile. */ PaintableComponent tileComponent = new PaintableComponent(tile); // The tile component initialization. { tileComponent.setBackground(Colors.white); tileComponent.setOpaque(true); } // The points XPoint2D P0 = new XPoint2D(100, 500); XPoint2D P1 = new XPoint2D(150, 100); XPoint2D P2 = new XPoint2D(500, 200); XPoint2D P3 = new XPoint2D(450, 450); XPoint2D Q0 = new XPoint2D(); XPoint2D Q1 = new XPoint2D(); XPoint2D Q2 = new XPoint2D(); XPoint2D R0 = new XPoint2D(); XPoint2D R1 = new XPoint2D(); XPoint2D S0 = new XPoint2D(); // The paints Paint paint0 = Colors.red; Paint paint1 = Colors.mediumvioletred; Paint paint2 = Colors.blueviolet; Paint paint3 = Colors.lightskyblue; /** The plotmark for the points. */ PlotMark mark = new PlotMark(PlotMark.FILLED_SQUARE, 5); /** The stroke for the cubic and the lines. */ BasicStroke stroke = new BasicStroke(2); /** The label font. */ Font font = null; /** The label locator strategy. */ TextAnchor.Locator locator = TextAnchor.CENTER_ASCENTLINE; /** * The tabbed pane to hold the cubic structure tab * and the cubic data tab. */ JTabbedPane tabbedPane = new JTabbedPane(); // The tabbed pane initialization. { tabbedPane.add("Cubic Structure", tileComponent); } /** The constructor to complete initialization. */ public CubicSubdivision() { add(tabbedPane); setLabelFont(); paintStructure(); } /** Set the font for the labels. */ void setLabelFont() { String name = Fonts.getMonospacedFontFamilyName(); int size = 16 + (int) LookAndFeelTools.getNetFontSizeAdjustment(); font = new Font(name, Font.BOLD, size); } /** * Perform the midpoint subdivision of the Bezier frame * defined by P0, P1, P2, P3. Place the data into * Q0, Q1, Q2, R0, R1, S0. */ void subdivide() { Q0.x = (P0.x + P1.x) / 2; Q0.y = (P0.y + P1.y) / 2; Q1.x = (P1.x + P2.x) / 2; Q1.y = (P1.y + P2.y) / 2; Q2.x = (P2.x + P3.x) / 2; Q2.y = (P2.y + P3.y) / 2; R0.x = (Q0.x + Q1.x) / 2; R0.y = (Q0.y + Q1.y) / 2; R1.x = (Q1.x + Q2.x) / 2; R1.y = (Q1.y + Q2.y) / 2; S0.x = (R0.x + R1.x) / 2; S0.y = (R0.y + R1.y) / 2; } /** Paint the cubic structure. */ void paintStructure() { subdivide(); sequence = new PaintableSequence(); appendPoints(); appendLabels(); appendCubic(); appendLines(); tile.setPaintable(sequence); } /** Append the points to the sequence. */ void appendPoints() { PointPaintable p0 = new PointPaintable(P0, mark, paint0); PointPaintable p1 = new PointPaintable(P1, mark, paint0); PointPaintable p2 = new PointPaintable(P2, mark, paint0); PointPaintable p3 = new PointPaintable(P3, mark, paint0); PointPaintable q0 = new PointPaintable(Q0, mark, paint1); PointPaintable q1 = new PointPaintable(Q1, mark, paint1); PointPaintable q2 = new PointPaintable(Q2, mark, paint1); PointPaintable r0 = new PointPaintable(R0, mark, paint2); PointPaintable r1 = new PointPaintable(R1, mark, paint2); PointPaintable s0 = new PointPaintable(S0, mark, paint3); sequence.addPaintable(p0); sequence.addPaintable(p1); sequence.addPaintable(p2); sequence.addPaintable(p3); sequence.addPaintable(q0); sequence.addPaintable(q1); sequence.addPaintable(q2); sequence.addPaintable(r0); sequence.addPaintable(r1); sequence.addPaintable(s0); } /** Append the point labels to the sequence. */ void appendLabels() { appendLabel("P0", P0, 10, paint0); appendLabel("P1", P1, 10, paint0); appendLabel("P2", P2, 10, paint0); appendLabel("P3", P3, 10, paint0); appendLabel("Q0", Q0, 10, paint1); appendLabel("Q1", Q1, 10, paint1); appendLabel("Q2", Q2, 10, paint1); appendLabel("R0", R0, 10, paint2); appendLabel("R1", R1, 10, paint2); appendLabel("S0", S0, 10, paint3); } /** Append the cubic curve to the sequence. */ void appendCubic() { float x0 = (float) P0.x; float y0 = (float) P0.y; float x1 = (float) P1.x; float y1 = (float) P1.y; float x2 = (float) P2.x; float y2 = (float) P2.y; float x3 = (float) P3.x; float y3 = (float) P3.y; GeneralPath path = new GeneralPath(); path.moveTo(x0, y0); path.curveTo(x1, y1, x2, y2, x3, y3); ShapePaintable cubic = new ShapePaintable (path, PaintMode.DRAW, null, Colors.black, stroke); sequence.appendPaintable(cubic); } /** Append the lines to the sequence. */ void appendLines() { appendLine(P0, P1, paint0); appendLine(P1, P2, paint0); appendLine(P2, P3, paint0); appendLine(Q0, Q1, paint1); appendLine(Q1, Q2, paint1); appendLine(R0, R1, paint2); } /** * Append the label * below the given point * by the given amount delta * using the given paint. */ void appendLabel (String label, XPoint2D a, double delta, Paint paint) { float x = (float) a.x; float y = (float) (a.y + delta); TextPaintable tp = new TextPaintable (label, font, paint, locator, x, y); sequence.appendPaintable(tp); } void appendLine(XPoint2D a, XPoint2D b, Paint paint) { XLine2D line = new XLine2D(a.x, a.y, b.x, b.y); ShapePaintable sp = new ShapePaintable (line, PaintMode.DRAW, null, paint, stroke); sequence.appendPaintable(sp); } /** * The main program to launch the cubic subdivision demo. * * @param args ignored */ public static void main(String[] args) { LookAndFeelTools.setNetFontSizeAdjustment(4); new CubicSubdivision().frame("Cubic Subdivision"); } }