class ClippyTriangles extends Triangles {
    ClippyTriangles(int N) {
        super(N, N/2);
    }
    int odd_one(boolean b0, boolean b1, boolean b2) {
        if(b0==b1)
            return 2;
        else if(b0==b2)
            return 1;
        else
            return 0;
    }
    final static double NEPS = -0.001;
    void clip(Triangles tris) {
        // reserve the first tris.nv_ vertex ids for the old, copy as needed
        nv_ = tris.nv_;
        for(int i = 0; i<tris.nf_; ++i) {
            boolean in0 = tris.vertices_[tris.faces_[i*3+0]].pt.z()<0.,
                in1 = tris.vertices_[tris.faces_[i*3+1]].pt.z()<0.,
                in2 = tris.vertices_[tris.faces_[i*3+2]].pt.z()<0.;
            int nin = (in0?1:0) + (in1?1:0) + (in2?1:0); //argh
            //System.out.print(" "+nin);
            switch(nin) {
            case 0:
                break;
            case 1: 
            case 2: {
                int odd = odd_one(in0,in1,in2),
                    newccw = nv_++, newcw = nv_++;
                PointyPoint 
                    podd = tris.vertices_[tris.faces_[i*3+odd]],
                    pccw = tris.vertices_[tris.faces_[i*3+(odd+1)%3]],
                    pcw = tris.vertices_[tris.faces_[i*3+(odd+2)%3]],
                    ccwc = extras_[nx_++],
                    cwc = extras_[nx_++];
                vertices_[newccw] = ccwc;
                vertices_[newcw] = cwc;
                //System.out.println("nin "+nin+" odd's "+podd.pt.z()+" versus "+pccw.pt.z()+" and "+pcw.pt.z());
                double tccw = -pccw.pt.z()/(podd.pt.z()-pccw.pt.z()),
                    tcw = -pcw.pt.z()/(podd.pt.z()-pcw.pt.z());
                pccw.pt.lerp(podd.pt,tccw,ccwc.pt);
                ccwc.pt.set(2,NEPS);
                pcw.pt.lerp(podd.pt,tcw,cwc.pt);
                cwc.pt.set(2,NEPS);
                //System.out.println("new pts "+ccwc.pt+" and "+cwc.pt);        
                pccw.v.lerp(podd.v,tccw,ccwc.v);
                pcw.v.lerp(podd.v,tcw,cwc.v);
                if(nin==1) {
                    vertices_[tris.faces_[i*3+odd]] = podd;
                    vertices_[tris.faces_[i*3+(odd+1)%3]] = 
                        vertices_[tris.faces_[i*3+(odd+2)%3]] = null;
                    faces_[nf_*3  ] = newcw;
                    faces_[nf_*3+1] = tris.faces_[i*3+odd];
                    faces_[nf_*3+2] = newccw;
                    for(int q=0; q<3; ++q)
                        if(vertices_[faces_[nf_*3+q]].pt.z()>0.)
                            System.out.println("A: badness in "+q);
                    ++nf_;
                }
                else {
                    vertices_[tris.faces_[i*3+odd]] = null;
                    vertices_[faces_[nf_*3+1] = tris.faces_[i*3+(odd+1)%3]] = pccw;
                    vertices_[faces_[nf_*3+2] = tris.faces_[i*3+(odd+2)%3]] = pcw;
                    faces_[nf_*3  ] = newcw;
                    for(int q=0; q<3; ++q)
                        if(vertices_[faces_[nf_*3+q]].pt.z()>0.)
                            System.out.println("B: badness in "+q);
                    ++nf_;
                    faces_[nf_*3  ] = newccw;
                    faces_[nf_*3+1] = tris.faces_[i*3+(odd+1)%3];
                    faces_[nf_*3+2] = newcw;
                    for(int q=0; q<3; ++q)
                        if(vertices_[faces_[nf_*3+q]].pt.z()>0.)
                            System.out.println("C: badness in "+q);
                    ++nf_;                  
                }
                break;
            }
            case 3:
                for(int j = 0; j<3; ++j) {
                    int f = tris.faces_[i*3+j];
                    vertices_[f] = tris.vertices_[f];
                    faces_[nf_*3+j] = tris.faces_[i*3+j];
                }
                ++nf_;
                break;
            }
        }
        //System.out.println("clip't "+nf_);
    }
}