//-*- eval: (progn (folding-mode) (auto-fill-mode 0)) -*- 
//[Update:[Fri Dec 11 IST 2020]]
/*History:
**Sat Oct 26 2019
   Started.
**Wed Oct 30 2019
 First working version.
**Sun Nov 10 2019
 Added svg group.
*/
import java.util.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
import javax.swing.*;

public class Cone extends Object3D {
    static int count = 0;
    double r, h;
    JTextField radFld, htFld;

    public Cone(Screen scr) {
        super(new Pose(scr,0,0,0,0,0,0), scr, "Cone"+Cone.count);
        count++;
        r = 5;
        h = 10;
        panel.add(new JLabel("Radius: "));
        radFld = new JTextField(""+r);
        htFld = new JTextField(""+h);
        panel.add(radFld);
        panel.add(new JLabel("Height: "));
        panel.add(htFld);
    }

    public void save(PrintWriter pw) {
        pw.format(" %f %f\n",r,h);
        pose.save(pw);
    }

    protected void load(Scanner scnr) {
        System.err.println("Loading a cone");
        double tmpr,tmph;
        try {
            tmpr = scnr.nextDouble();
            tmph = scnr.nextDouble();
            pose.load(scnr);
        }
        catch(Exception ex) {
            System.err.println("Failed to load cone");
            ex.printStackTrace(System.err);
            return;
        }
        r = tmpr; h = tmph;
        scr.repaint();
    }
    
    protected void updating() {
        r = Double.parseDouble(radFld.getText());
        h = Double.parseDouble(htFld.getText());
    }
    protected void fillGui() {
        radFld.setText(""+r);
        htFld.setText(""+h);
    }

    public void dump(Camera cam, Pad pad) {
        // {{{ Check if missed or not

        Vec3 c = pose.invRot(pose.getOrigin().minus(cam.getOrigin()));
        Vec3 scales = pose.getScales();
        double xScale = scales.x;
        double yScale = scales.y;
        double zScale = scales.z;
        double agamma = c.x*zScale;
        double calpha = c.z*xScale;
        
        double off = Math.atan2(agamma, calpha);
        double sin = -r*xScale*zScale* (1+c.y/(h*yScale)) / Math.sqrt(agamma*agamma+calpha*calpha);
        boolean missed = Math.abs(sin) > 1;

        // }}}

        double delta = Math.PI/50.0;
        double theta;
        double gap; int n;
        

        if(missed) {
            // {{{ Draw bottom ellipse in one piece
            pad.startGroup();
            pad.startPath();
            for(theta=0;theta<=2*Math.PI;theta+= 0.01) {
                Vec3 tmp = pose.wrt(new Vec3(r*Math.cos(theta), 0, r*Math.sin(theta)));
                pad.addPoint(cam.see(tmp));
            }
            pad.endPath();
            pad.endGroup();
            // }}}
            return;
        }

        // {{{ Find theta0 and theta1
        
        double t = Math.asin(sin);
        double theta0 = t-off;
        double theta1 = -Math.PI-t-off;
        //System.err.println("theta0 = "+theta0+", theta1 = "+theta1);
        
        // }}}
        pad.startGroup();
        // {{{ Side lines
        
        Vec3 botCentre = pose.getOrigin();
        Vec3 apex = pose.wrt(new Vec3(0,h,0));
        Vec3 bot1 = pose.wrt(new Vec3(r*Math.cos(theta0), 0, r*Math.sin(theta0)));
        Vec3 bot2 = pose.wrt(new Vec3(r*Math.cos(theta1), 0, r*Math.sin(theta1)));
        
        Vec2 papex = cam.see(apex);
        Vec2 pbot1 = cam.see(bot1);
        Vec2 pbot2 = cam.see(bot2);
        pad.startPath();
        pad.addPoint(pbot1);
        pad.addPoint(papex);
        pad.addPoint(pbot2);
        pad.endPath();
    
        // }}}

        // {{{ Bottom ellipse
        
        // {{{ One part 
        gap = theta0 - theta1;
        n = (int)(50*gap/Math.PI);
        delta = gap/n;
        theta=theta1;
        pad.startPath();
        for(int i=0;i<=n;i++) {
            Vec3 tmp = pose.wrt(new Vec3(r*Math.cos(theta), 0, r*Math.sin(theta)));
            pad.addPoint(cam.see(tmp));
            theta += delta;
        }
        pad.endPath();
        // }}}
        // {{{ The other part
        gap = (2*Math.PI+theta1) - theta0;
        n = (int)(50*gap/Math.PI);
        delta = gap/n;
        theta=theta0;
        pad.startPath();
        for(int i=0;i<=n;i++) {
            Vec3 tmp = pose.wrt(new Vec3(r*Math.cos(theta), 0, r*Math.sin(theta)));
            pad.addPoint(cam.see(tmp));
            theta += delta;
        }
        pad.endPath();
        // }}}
        // }}}

        pad.endGroup();

    }
}
