/* @(#)PathShapes.java   15 September 2005 */

/* Useful imports */

import edu.neu.ccs.*;
import edu.neu.ccs.gui.*;
import edu.neu.ccs.codec.*;
import edu.neu.ccs.console.*;
import edu.neu.ccs.filter.*;
import edu.neu.ccs.jpf.*;
import edu.neu.ccs.parser.*;
import edu.neu.ccs.pedagogy.*;
import edu.neu.ccs.quick.*;
import edu.neu.ccs.util.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.*;
import java.util.*;
import java.math.*;
import java.beans.*;
import java.lang.reflect.*;
import java.net.URL;
import java.util.regex.*;
import java.text.ParseException;

public class PathShapes extends JPF 
{
    
    public static void main(String[] args) { 
        LookAndFeelTools.adjustAllDefaultFontSizes(4);
        
        new PathShapes();
    }
    
    public void ShowQuadShape
        (float x0, float y0,
         float x1, float y1,
         float x2, float y2)
    {
        GeneralPath path = new GeneralPath();
        
        path.moveTo(x0, y0);
        path.quadTo(x1, y1, x2, y2);
        
        Graphics2D g = window.getBufferGraphics();
        
        Color fill = Colors.transparent;
        Color draw = Colors.black;
        
        Path.showShapeStructure(g, path, fill, draw, 2);
        window.repaint();
    }
    
    
    public void ShowCubicShape
        (float x0, float y0,
         float x1, float y1,
         float x2, float y2,
         float x3, float y3)
    {
        GeneralPath path = new GeneralPath();
        
        path.moveTo(x0, y0);
        path.curveTo(x1, y1, x2, y2, x3, y3);
        
        Graphics2D g = window.getBufferGraphics();
        
        Color fill = Colors.transparent;
        Color draw = Colors.black;
        
        Path.showShapeStructure(g, path, fill, draw, 2);
        window.repaint();
    }


    public void ShowQuadSubdivision
        (float x0, float y0,
         float x1, float y1,
         float x2, float y2,
         int level, boolean showAll)
    {
        Graphics2D g = window.getBufferGraphics();
        
        Color draw = Colors.black;
        g.setPaint(draw);
        
        //BasicStroke stroke = new BasicStroke(2);
        //g.setStroke(stroke);
        
        g.setRenderingHint
            (RenderingHints.KEY_ANTIALIASING,
             RenderingHints.VALUE_ANTIALIAS_ON);
        
        ShowQuadSubdivision
            (g, x0, y0, x1, y1, x2, y2, level, showAll);
        
        window.repaint();
    }
    
    
    private void ShowQuadSubdivision
        (Graphics2D g,
         float x0, float y0,
         float x1, float y1,
         float x2, float y2,
         int level, boolean showAll)
    {
        // handle this level
        if (showAll || (level == 0)) {
            XLine2D line = new XLine2D();
            
            line.setLine(x0, y0, x1, y1);
            g.draw(line);
            
            line.setLine(x1, y1, x2, y2);
            g.draw(line);
        }
        
        if (level <= 0)
            return;
        
        // prepare recursion
        
        level--;
        
        float p0 = (x0 + x1) / 2;
        float q0 = (y0 + y1) / 2;
        
        float p1 = (x1 + x2) / 2;
        float q1 = (y1 + y2) / 2;
        
        float r0 = (p0 + p1) / 2;
        float s0 = (q0 + q1) / 2;
        
        ShowQuadSubdivision
            (g, x0, y0, p0, q0, r0, s0, level, showAll);
        
        ShowQuadSubdivision
            (g, r0, s0, p1, q1, x2, y2, level, showAll);
    }
    
    
    public void ShowCubicSubdivision
        (float x0, float y0,
         float x1, float y1,
         float x2, float y2,
         float x3, float y3,
         int level, boolean showAll)
    {
        Graphics2D g = window.getBufferGraphics();
        
        Color draw = Colors.black;
        g.setPaint(draw);
        
        //BasicStroke stroke = new BasicStroke(2);
        //g.setStroke(stroke);
        
        g.setRenderingHint
            (RenderingHints.KEY_ANTIALIASING,
             RenderingHints.VALUE_ANTIALIAS_ON);
        
        ShowCubicSubdivision
            (g, x0, y0, x1, y1, x2, y2, x3, y3, level, showAll);
        
        window.repaint();
    }
    
    
    private void ShowCubicSubdivision
        (Graphics2D g,
         float x0, float y0,
         float x1, float y1,
         float x2, float y2,
         float x3, float y3,
         int level, boolean showAll)
    {
        // handle this level
        if (showAll || (level == 0)) {
            XLine2D line = new XLine2D();
            
            line.setLine(x0, y0, x1, y1);
            g.draw(line);
            
            line.setLine(x1, y1, x2, y2);
            g.draw(line);
            
            line.setLine(x2, y2, x3, y3);
            g.draw(line);
        }
        
        if (level <= 0)
            return;
        
        // prepare recursion
        
        level--;
        
        float p0 = (x0 + x1) / 2;
        float q0 = (y0 + y1) / 2;
        
        float p1 = (x1 + x2) / 2;
        float q1 = (y1 + y2) / 2;
        
        float p2 = (x2 + x3) / 2;
        float q2 = (y2 + y3) / 2;
        
        float r0 = (p0 + p1) / 2;
        float s0 = (q0 + q1) / 2;
        
        float r1 = (p1 + p2) / 2;
        float s1 = (q1 + q2) / 2;
        
        float t0 = (r0 + r1) / 2;
        float u0 = (s0 + s1) / 2;
        
        ShowCubicSubdivision
            (g, x0, y0, p0, q0, r0, s0, t0, u0, level, showAll);
        
        ShowCubicSubdivision
            (g, t0, u0, r1, s1, p2, q2, x3, y3, level, showAll);
    }
    
    
    XCircle circle = new XCircle(200, 200, 100);
    
    
    public void CircleShapeStructure() {
        window.clearPanelAndSequence();
        Graphics2D g = window.getBufferGraphics();
        
        Color fill = Colors.green;
        Color draw = Colors.black;
        
        Path.showShapeStructure(g, circle, fill, draw, 2);
        window.repaint();
    }
    
    
    public void PrintCircleShapeData() {
        String data = Path.shapeToString(circle);
        
        console.out.println("Circle Path Data");
        console.out.println();
        
        console.out.println(data);
        console.out.println();
    }
    
    
    /**
     * This method creates a path using all 5 path operations
     * and having 3 distinct regions.
     * 
     * The path has no particular meaning other than as a
     * sample of the various path operations. 
     */
    public void SamplePath() {
        GeneralPath path = new GeneralPath();
        
        path.moveTo(100, 100);
        path.lineTo(300, 100);
        path.quadTo(350, 200, 300, 300);
        path.curveTo(250, 225, 150, 375, 100, 300);
        path.closePath();
        
        path.moveTo(100, 50);
        path.lineTo(200, 75);
        path.lineTo(300, 50);
        path.closePath();
        
        path.moveTo(50, 100);
        path.curveTo(90, 300, 10, 300, 50, 100);
        path.closePath();
        
        window.clearPanelAndSequence();
        Graphics2D g = window.getBufferGraphics();
        
        Color fill = Colors.green;
        Color draw = Colors.black;
        
        Path.showShapeStructure(g, path, fill, draw, 2);
        window.repaint();
    }
    
    
    public void ShowGeneralPathConstants() {
        console.out.println("GeneralPath Constants");
        console.out.println();
        
        console.out.println
            ("GeneralPath.WIND_EVEN_ODD: " + GeneralPath.WIND_EVEN_ODD);
        console.out.println
            ("GeneralPath.WIND_NON_ZERO: " + GeneralPath.WIND_NON_ZERO);
        console.out.println();
    }
    
    
    public void ShowPathIteratorConstants() {
        console.out.println("PathIterator Constants");
        console.out.println();
        
        console.out.println
            ("PathIterator.SEG_MOVETO:  " + PathIterator.SEG_MOVETO);
        console.out.println
            ("PathIterator.SEG_LINETO:  " + PathIterator.SEG_LINETO);
        console.out.println
            ("PathIterator.SEG_QUADTO:  " + PathIterator.SEG_QUADTO);
        console.out.println
            ("PathIterator.SEG_CUBICTO: " + PathIterator.SEG_CUBICTO);
        console.out.println
            ("PathIterator.SEG_CLOSE:   " + PathIterator.SEG_CLOSE);
        console.out.println();
    }
}
