/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOUSE. See the GNU
 * General Public License for more details.
 *
 * You should have recieved a copy of the GNU General Public License
 * along with this program; if not write to the Free Software
 * Foundation, inc., 59 Temple Place, Suite 330, Boston MA 02111-1307
 * USA
 */
package j3d;
import java.awt.geom.Rectangle2D;
import java.io.*;
import java.util.*;

import javax.swing.*;
import javax.swing.tree.*;

import gui.*;
/**
 * Insert the type's description here.
 *
 * @author: Yuriy Mikhaylovskiy
 */

public class _Stl extends _Object implements Serializable{
  //public Color color;
  private Vector nodesDB = new Vector();
  private Vector elementsDB = new Vector();
  private Hashtable nodes;
  private Vector elements;
  private Hashtable nodes_tmp;
  private Vector elements_tmp;
  private String file_name;
  private String msh_name = "Shell_C0_3";
  private int msh_type = Canvas3D.MESH_Shell_C0_3;
  public boolean selected = false;
  private DefaultMutableTreeNode treeNode;
  private Vector arr;

  private void writeObject(ObjectOutputStream out)  throws IOException{
    out.writeObject(nodesDB);
    out.writeObject(elementsDB);
    out.writeObject(file_name);
    out.writeObject(msh_name);
    out.writeInt(msh_type);
    out.writeBoolean(selected);
    out.writeObject(Id);
  }
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
    nodesDB = (Vector)in.readObject();
    elementsDB = (Vector)in.readObject();
    file_name = (String)in.readObject();
    msh_name = (String)in.readObject();
    msh_type = in.readInt();
    selected = in.readBoolean();
    Id = (String)in.readObject();
    for(int i=0; i<nodesDB.size(); i++) ((_Object)nodesDB.elementAt(i)).set_Id(i+"");
    for(int i=0; i<elementsDB.size(); i++) ((_Object)elementsDB.elementAt(i)).set_Id(i+"");
  }


  public void reset() {};

  public void mesh(int type, float size){
    if(!selected)return;
    if(Canvas3D.MESH_Contact_Triangle==type) msh_name="Contact_Triangle";
    else if(Canvas3D.MESH_Shell_C0_3==type) msh_name="Shell_C0_3";
    else if(Canvas3D.MESH_Shell_BT_4==type) msh_name="Shell_BT_4";
    else if(Canvas3D.MESH_Solid_Iso_6==type) msh_name="Solid_Iso_6";
    else return;
    msh_type=type;
    System.out.println("\nMesh type - "+msh_name+"\nMesh size - "+size);
    nodes_tmp.clear();
    elements_tmp.removeAllElements();
    //elements_err.removeAllElements();
    float xmin=Float.MAX_VALUE;
    float ymin=Float.MAX_VALUE;
    float zmin=Float.MAX_VALUE;
    float xmax=Float.MIN_VALUE;
    float ymax=Float.MIN_VALUE;
    float zmax=Float.MIN_VALUE;
    for (Enumeration e = nodes.keys(); e.hasMoreElements();) {
      String key = e.nextElement()+"";
      float[] nd = (float[])nodes.get(key);
      xmin=Math.min(xmin,nd[0]);
      ymin=Math.min(ymin,nd[1]);
      zmin=Math.min(zmin,nd[2]);
      xmax=Math.max(xmax,nd[0]);
      ymax=Math.max(ymax,nd[1]);
      zmax=Math.max(zmax,nd[2]);
    }
    System.out.println("\nBounding box:\n"+xmin+",\t"+ymin+",\t"+zmin+"\n"+xmax+",\t"+ymax+",\t"+zmax);
    for(float z=zmin; z<=zmax; z+=size){
      for(float x=xmin; x<=xmax; x+=size){
        for(int i=0; i<elements.size(); i++){
          String[] nds = (String[])elements.elementAt(i);
          float[] nd0 = (float[])nodes.get(nds[0]);
          float[] nd1 = (float[])nodes.get(nds[1]);
          float[] nd2 = (float[])nodes.get(nds[2]);
          float[] p = lib3D.PL3T_LINE(new _Point(nd0[0],nd0[1],nd0[2]),new _Point(nd1[0],nd1[1],nd1[2]),new _Point(nd2[0],nd2[1],nd2[2]),new _Point(x,Float.MIN_VALUE,z),new _Point(x,Float.MAX_VALUE,z));
          if(p!=null){nodes_tmp.put((p[0]+"_"+p[1]+"_"+p[2]).replaceAll("-0.0_","0.0_"),p);}
        }
      }
      for(float y=ymin; y<=ymax; y+=size){
        for(int i=0; i<elements.size(); i++){
          String[] nds = (String[])elements.elementAt(i);
          float[] nd0 = (float[])nodes.get(nds[0]);
          float[] nd1 = (float[])nodes.get(nds[1]);
          float[] nd2 = (float[])nodes.get(nds[2]);
          float[] p = lib3D.PL3T_LINE(new _Point(nd0[0],nd0[1],nd0[2]),new _Point(nd1[0],nd1[1],nd1[2]),new _Point(nd2[0],nd2[1],nd2[2]),new _Point(Float.MIN_VALUE,y,z),new _Point(Float.MAX_VALUE,y,z));
          if(p!=null){nodes_tmp.put((p[0]+"_"+p[1]+"_"+p[2]).replaceAll("-0.0_","0.0_"),p);}
        }
      }
    }
    for(float x=xmin; x<=xmax; x+=size){
      for(float y=ymin; y<=ymax; y+=size){
        for(int i=0; i<elements.size(); i++){
          String[] nds = (String[])elements.elementAt(i);
          float[] nd0 = (float[])nodes.get(nds[0]);
          float[] nd1 = (float[])nodes.get(nds[1]);
          float[] nd2 = (float[])nodes.get(nds[2]);
          float[] p = lib3D.PL3T_LINE(new _Point(nd0[0],nd0[1],nd0[2]),new _Point(nd1[0],nd1[1],nd1[2]),new _Point(nd2[0],nd2[1],nd2[2]),new _Point(x,y,Float.MIN_VALUE),new _Point(x,y,Float.MAX_VALUE));
          if(p!=null){nodes_tmp.put((p[0]+"_"+p[1]+"_"+p[2]).replaceAll("-0.0_","0.0_"),p);}
        }
      }
    }
    System.out.println("\nNodes intersection - "+nodes_tmp.size());
    if(msh_type==Canvas3D.MESH_Solid_Iso_6){
      for(float z=zmin; z<zmax; z+=size){
        for(float y=ymin; y<ymax; y+=size){
          for(float x=xmin; x<xmax; x+=size){
            float[] p1 = new float[3];
            p1[0]=x; p1[1]=y; p1[2]=z;
            float[] p2 = new float[3];
            p2[0]=x+size; p2[1]=y; p2[2]=z;
            float[] p3 = new float[3];
            p3[0]=x+size; p3[1]=y+size; p3[2]=z;
            float[] p4 = new float[3];
            p4[0]=x; p4[1]=y+size; p4[2]=z;
            float[] p5 = new float[3];
            p5[0]=x; p5[1]=y; p5[2]=z+size;
            float[] p6 = new float[3];
            p6[0]=x+size; p6[1]=y; p6[2]=z+size;
            float[] p7 = new float[3];
            p7[0]=x+size; p7[1]=y+size; p7[2]=z+size;
            float[] p8 = new float[3];
            p8[0]=x; p8[1]=y+size; p8[2]=z+size;
            String[] snd = new String[8];
            snd[0]=(p1[0]+"_"+p1[1]+"_"+p1[2]).replaceAll("-0.0_","0.0_");
            snd[1]=(p2[0]+"_"+p2[1]+"_"+p2[2]).replaceAll("-0.0_","0.0_");
            snd[2]=(p3[0]+"_"+p3[1]+"_"+p3[2]).replaceAll("-0.0_","0.0_");
            snd[3]=(p4[0]+"_"+p4[1]+"_"+p4[2]).replaceAll("-0.0_","0.0_");
            snd[4]=(p5[0]+"_"+p5[1]+"_"+p5[2]).replaceAll("-0.0_","0.0_");
            snd[5]=(p6[0]+"_"+p6[1]+"_"+p6[2]).replaceAll("-0.0_","0.0_");
            snd[6]=(p7[0]+"_"+p7[1]+"_"+p7[2]).replaceAll("-0.0_","0.0_");
            snd[7]=(p8[0]+"_"+p8[1]+"_"+p8[2]).replaceAll("-0.0_","0.0_");
            boolean p1exist = contains(x,y,z);
            boolean p2exist = contains(x+size,y,z);
            boolean p3exist = contains(x+size,y+size,z);
            boolean p4exist = contains(x,y+size,z);
            boolean p5exist = contains(x,y,z+size);
            boolean p6exist = contains(x+size,y,z+size);
            boolean p7exist = contains(x+size,y+size,z+size);
            boolean p8exist = contains(x,y+size,z+size);
            if(p1exist && p2exist && p3exist && p4exist && p5exist && p6exist && p7exist && p8exist){
              elements_tmp.addElement(snd);
              nodes_tmp.put(snd[0],p1);
              nodes_tmp.put(snd[1],p2);
              nodes_tmp.put(snd[2],p3);
              nodes_tmp.put(snd[3],p4);
              nodes_tmp.put(snd[4],p5);
              nodes_tmp.put(snd[5],p6);
              nodes_tmp.put(snd[6],p7);
              nodes_tmp.put(snd[7],p8);
            }
          }
        }
      }
      //===================================================
      long date = new java.util.Date().getTime();
      for(float z=zmin; z<zmax; z+=size){
        for(float y=ymin; y<ymax; y+=size){
          for(float x=xmin; x<xmax; x+=size){
            float[] p1 = new float[3];
            p1[0]=x; p1[1]=y; p1[2]=z;
            float[] p2 = new float[3];
            p2[0]=x+size; p2[1]=y; p2[2]=z;
            float[] p3 = new float[3];
            p3[0]=x+size; p3[1]=y+size; p3[2]=z;
            float[] p4 = new float[3];
            p4[0]=x; p4[1]=y+size; p4[2]=z;
            float[] p5 = new float[3];
            p5[0]=x; p5[1]=y; p5[2]=z+size;
            float[] p6 = new float[3];
            p6[0]=x+size; p6[1]=y; p6[2]=z+size;
            float[] p7 = new float[3];
            p7[0]=x+size; p7[1]=y+size; p7[2]=z+size;
            float[] p8 = new float[3];
            p8[0]=x; p8[1]=y+size; p8[2]=z+size;
            String[] snd = new String[8];
            snd[0]=(p1[0]+"_"+p1[1]+"_"+p1[2]).replaceAll("-0.0_","0.0_");
            snd[1]=(p2[0]+"_"+p2[1]+"_"+p2[2]).replaceAll("-0.0_","0.0_");
            snd[2]=(p3[0]+"_"+p3[1]+"_"+p3[2]).replaceAll("-0.0_","0.0_");
            snd[3]=(p4[0]+"_"+p4[1]+"_"+p4[2]).replaceAll("-0.0_","0.0_");
            snd[4]=(p5[0]+"_"+p5[1]+"_"+p5[2]).replaceAll("-0.0_","0.0_");
            snd[5]=(p6[0]+"_"+p6[1]+"_"+p6[2]).replaceAll("-0.0_","0.0_");
            snd[6]=(p7[0]+"_"+p7[1]+"_"+p7[2]).replaceAll("-0.0_","0.0_");
            snd[7]=(p8[0]+"_"+p8[1]+"_"+p8[2]).replaceAll("-0.0_","0.0_");
            boolean p1exist = contains(x,y,z);
            boolean p2exist = contains(x+size,y,z);
            boolean p3exist = contains(x+size,y+size,z);
            boolean p4exist = contains(x,y+size,z);
            boolean p5exist = contains(x,y,z+size);
            boolean p6exist = contains(x+size,y,z+size);
            boolean p7exist = contains(x+size,y+size,z+size);
            boolean p8exist = contains(x,y+size,z+size);
            int corner = 0; if(p1exist)corner++; if(p2exist)corner++; if(p3exist)corner++; if(p4exist)corner++; if(p5exist)corner++; if(p6exist)corner++; if(p7exist)corner++; if(p8exist)corner++;
            if(p1exist && p2exist && p3exist && p4exist && p5exist && p6exist && p7exist && p8exist){
            }else{
              Vector nv = new Vector();
              for (Enumeration e = nodes_tmp.keys(); e.hasMoreElements();) {
                String key = e.nextElement()+"";
                float[] narr = (float[])nodes_tmp.get(key);
                if(x<=narr[0] && narr[0]<=x+size && y<=narr[1] && narr[1]<=y+size && z<=narr[2] && narr[2]<=z+size){
                  nv.addElement(narr);
                }
              }
              if(p1exist && p2exist && p3exist && p4exist && !p5exist && !p6exist && !p7exist && !p8exist && (nv.size()==8 || nv.size()==9)){
                System.out.println("mesh N1->"+nv.size());
                for(int i=0; i<nv.size(); i++){
                  float[] n = (float[])nv.elementAt(i);
                  if(x==n[0] && y==n[1] && z<n[2]){
                    snd[4]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size==n[0] && y==n[1] && z<n[2]){
                    snd[5]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size==n[0] && y+size==n[1] && z<n[2]){
                    snd[6]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x==n[0] && y+size==n[1] && z<n[2]){
                    snd[7]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }
                }
                elements_tmp.addElement(snd);
              }else if(!p1exist && !p2exist && !p3exist && !p4exist && p5exist && p6exist && p7exist && p8exist && (nv.size()==8 || nv.size()==9)){
                System.out.println("mesh N2->"+nv.size());
                for(int i=0; i<nv.size(); i++){
                  float[] n = (float[])nv.elementAt(i);
                  if(x==n[0] && y==n[1] && z+size>n[2]){
                    snd[0]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size==n[0] && y==n[1] && z+size>n[2]){
                    snd[1]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size==n[0] && y+size==n[1] && z+size>n[2]){
                    snd[2]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x==n[0] && y+size==n[1] && z+size>n[2]){
                    snd[3]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }
                }
                elements_tmp.addElement(snd);
              }else if(p1exist && !p2exist && !p3exist && p4exist && p5exist && !p6exist && !p7exist && p8exist && (nv.size()==8 || nv.size()==9)){
                System.out.println("mesh N3->"+nv.size());
                for(int i=0; i<nv.size(); i++){
                  float[] n = (float[])nv.elementAt(i);
                  if(x<n[0] && y==n[1] && z==n[2]){
                    snd[1]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x<n[0] && y+size==n[1] && z==n[2]){
                    snd[2]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x<n[0] && y==n[1] && z+size==n[2]){
                    snd[5]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x<n[0] && y+size==n[1] && z+size==n[2]){
                    snd[6]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }
                }
                elements_tmp.addElement(snd);
              }else if(!p1exist && p2exist && p3exist && !p4exist && !p5exist && p6exist && p7exist && !p8exist && (nv.size()==8 || nv.size()==9)){
                System.out.println("mesh N4->"+nv.size());
                for(int i=0; i<nv.size(); i++){
                  float[] n = (float[])nv.elementAt(i);
                  if(x+size>n[0] && y==n[1] && z==n[2]){
                    snd[0]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size>n[0] && y+size==n[1] && z==n[2]){
                    snd[3]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size>n[0] && y==n[1] && z+size==n[2]){
                    snd[4]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size>n[0] && y+size==n[1] && z+size==n[2]){
                    snd[7]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }
                }
                elements_tmp.addElement(snd);
              }else if(p1exist && p2exist && !p3exist && !p4exist && p5exist && p6exist && !p7exist && !p8exist && (nv.size()==8 || nv.size()==9)){
                System.out.println("mesh N5->"+nv.size());
                for(int i=0; i<nv.size(); i++){
                  float[] n = (float[])nv.elementAt(i);
                  if(x+size==n[0] && y<n[1] && z==n[2]){
                    snd[2]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x==n[0] && y<n[1] && z==n[2]){
                    snd[3]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size==n[0] && y<n[1] && z+size==n[2]){
                    snd[6]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x==n[0] && y<n[1] && z+size==n[2]){
                    snd[7]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }
                }
                elements_tmp.addElement(snd);
              }else if(!p1exist && !p2exist && p3exist && p4exist && !p5exist && !p6exist && p7exist && p8exist && (nv.size()==8 || nv.size()==9)){
                System.out.println("mesh N6->"+nv.size());
                for(int i=0; i<nv.size(); i++){
                  float[] n = (float[])nv.elementAt(i);
                  if(x==n[0] && y+size>n[1] && z==n[2]){
                    snd[0]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size==n[0] && y+size>n[1] && z==n[2]){
                    snd[1]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x==n[0] && y+size>n[1] && z+size==n[2]){
                    snd[4]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }else if(x+size==n[0] && y+size>n[1] && z+size==n[2]){
                    snd[5]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                  }
                }
                elements_tmp.addElement(snd);
              }else if((nv.size()==4 || nv.size()==5) && corner==0){
                System.out.println("mesh NX->"+nv.size()+" - "+corner);
              }else if(nv.size()==8){
                System.out.println("mesh NX->"+nv.size()+" - "+corner);
              }/*else if((nv.size()==4 || nv.size()==5)&& corner==1){
                System.out.println("mesh N4_5->"+nv.size());
                float[] n0 = (float[])nv.elementAt(0);
                float[] n1 = (float[])nv.elementAt(1);
                float[] n2 = (float[])nv.elementAt(2);
                float[] n3 = (float[])nv.elementAt(3);
                snd[0]=(n0[0]+"_"+n0[1]+"_"+n0[2]).replaceAll("-0.0_","0.0_");
                snd[1]=(n1[0]+"_"+n1[1]+"_"+n1[2]).replaceAll("-0.0_","0.0_");
                snd[2]=(n2[0]+"_"+n2[1]+"_"+n2[2]).replaceAll("-0.0_","0.0_");
                snd[3]=snd[2];
                snd[4]=(n3[0]+"_"+n3[1]+"_"+n3[2]).replaceAll("-0.0_","0.0_");
                snd[5]=snd[4]; snd[6]=snd[4]; snd[7]=snd[4];
                elements_tmp.addElement(snd);
              }*/else{
                String[] snd_tmp = new String[nv.size()];
                for(int i=0; i<nv.size(); i++){
                  float[] n = (float[])nv.elementAt(i);
                  snd_tmp[i]=(n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_");
                }
                if(snd_tmp.length==4/* || snd_tmp.length==5*/){
                  for(int i=0; i<snd_tmp.length; i++){
                    if(snd[0].equals(snd_tmp[i]) || snd[1].equals(snd_tmp[i]) || snd[2].equals(snd_tmp[i]) || snd[3].equals(snd_tmp[i]) || snd[4].equals(snd_tmp[i]) || snd[5].equals(snd_tmp[i]) || snd[6].equals(snd_tmp[i]) || snd[7].equals(snd_tmp[i])){
                      String stmp = snd_tmp[0];
                      snd_tmp[0]=snd_tmp[i];
                      snd_tmp[i]=stmp;
                    }
                  }
                }
                elements_tmp.addElement(snd_tmp);
              }/*else if(nv.size()<4 && !p1exist && !p2exist && !p3exist && !p4exist && !p5exist && !p6exist && !p7exist && !p8exist){
                for(int i=0; i<nv.size(); i++){
                  float[] n = (float[])nv.elementAt(i);
                  nodes_tmp.remove((n[0]+"_"+n[1]+"_"+n[2]).replaceAll("-0.0_","0.0_"));
                }
              }*/
            }


          }
        }
      }
      for(int i=0; i<elements_tmp.size(); i++){
        String[] sel = (String[])elements_tmp.elementAt(i);
        if(sel.length==4/* || sel.length==5*/){
          float[] nx = {0,0,0};
          for(int j=1; j<sel.length; j++){
            float[] nn = (float[])nodes_tmp.get(sel[j]);
            nx[0]+=nn[0];
            nx[1]+=nn[1];
            nx[2]+=nn[2];
          }
          nx[0]/=(sel.length-1);
          nx[1]/=(sel.length-1);
          nx[2]/=(sel.length-1);
          String nnode = (nx[0]+"_"+nx[1]+"_"+nx[2]).replaceAll("-0.0_","0.0_");
          nodes_tmp.put(nnode,nx);
          String[] rnodes = new String[sel.length-1];
          for(int j=0; j<rnodes.length; j++){
            rnodes[j]=sel[j+1];
          }
          change_nodes(rnodes,nnode);
          elements_tmp.remove(i);
          i--;
        }
      }
      for(int i=0; i<elements_tmp.size(); i++){
        String[] sel = (String[])elements_tmp.elementAt(i);
        if(sel.length!=8){
          elements_tmp.remove(i);
          i--;
        }
      }
      System.out.println(new java.util.Date().getTime() - date);





    }else if(msh_type==Canvas3D.MESH_Shell_BT_4){

    }else if(msh_type==Canvas3D.MESH_Contact_Triangle || msh_type==Canvas3D.MESH_Shell_C0_3){

    }
    System.out.println("\nNodes - "+nodes_tmp.size());
    System.out.println("Elements - "+elements_tmp.size());
  }

  private void change_nodes(String[] rnodes, String nnodes){
    for(int i=0; i<elements_tmp.size(); i++){
      String[] snodes = (String[])elements_tmp.elementAt(i);
      for(int j=0; j<snodes.length; j++){
        for(int k=0; k<rnodes.length; k++){
          if(snodes[j].equals(rnodes[k]))snodes[j]=nnodes;
        }
      }
      elements_tmp.setElementAt(snodes,i);
    }
    System.out.println("\n----------------Nodes - "+nodes_tmp.size());
    for(int k=0; k<rnodes.length; k++){
      nodes_tmp.remove(rnodes[k]);
      System.out.print(rnodes[k]+"\t");
    }
    System.out.println("\n----------Nodes - "+nodes_tmp.size()+"\t"+nnodes);

  }

  private boolean contains(float x, float y, float z){
    Vector v = new Vector();
    boolean xy = false; boolean xz = false; boolean yz = false;
    for(int i=0; i<elements.size(); i++){
      String[] nds = (String[])elements.elementAt(i);
      float[] nd0 = (float[])nodes.get(nds[0]);
      float[] nd1 = (float[])nodes.get(nds[1]);
      float[] nd2 = (float[])nodes.get(nds[2]);
      float[] p = lib3D.PL3T_LINE(new _Point(nd0[0],nd0[1],nd0[2]),new _Point(nd1[0],nd1[1],nd1[2]),new _Point(nd2[0],nd2[1],nd2[2]),new _Point(x,Float.MIN_VALUE,z),new _Point(x,Float.MAX_VALUE,z));
      boolean exist = false;
      for(int j=0; p!=null && j<v.size(); j++){
        if(((Float)v.elementAt(j)).floatValue()==p[1])exist=true;
      }
      if(p!=null && !exist){v.addElement(new Float(p[1]));}
    }
    float[] arr = new float[v.size()];
    if(((int)(arr.length/2))*2==arr.length){
      for(int i=0; i<v.size(); i++){
        arr[i] = ((Float)v.elementAt(i)).floatValue();
      }
      for(int i=0; i<arr.length; i++){
        for(int j=i; j<arr.length; j++){
          if(arr[i]>arr[j]){
            float a=arr[i];
            arr[i]=arr[j];
            arr[j]=a;
          }
        }
      }
      for(int i=0; i<arr.length/2; i++){
        if(arr[i*2]<=y && arr[i*2+1]>=y)return true;
      }
    }else if(arr.length>0)xz=true;
    v = new Vector();
    for(int i=0; i<elements.size(); i++){
      String[] nds = (String[])elements.elementAt(i);
      float[] nd0 = (float[])nodes.get(nds[0]);
      float[] nd1 = (float[])nodes.get(nds[1]);
      float[] nd2 = (float[])nodes.get(nds[2]);
      float[] p = lib3D.PL3T_LINE(new _Point(nd0[0],nd0[1],nd0[2]),new _Point(nd1[0],nd1[1],nd1[2]),new _Point(nd2[0],nd2[1],nd2[2]),new _Point(x,y,Float.MIN_VALUE),new _Point(x,y,Float.MAX_VALUE));
      boolean exist = false;
      for(int j=0; p!=null && j<v.size(); j++){
        if(((Float)v.elementAt(j)).floatValue()==p[2])exist=true;
      }
      if(p!=null && !exist){v.addElement(new Float(p[2]));}
    }
    arr = new float[v.size()];
    if(((int)(arr.length/2))*2==arr.length){
      for(int i=0; i<v.size(); i++){
        arr[i] = ((Float)v.elementAt(i)).floatValue();
      }
      for(int i=0; i<arr.length; i++){
        for(int j=i; j<arr.length; j++){
          if(arr[i]>arr[j]){
            float a=arr[i];
            arr[i]=arr[j];
            arr[j]=a;
          }
        }
      }
      for(int i=0; i<arr.length/2; i++){
        if(arr[i*2]<=z && arr[i*2+1]>=z)return true;
      }
    }else if(arr.length>0)xy=true;
    v = new Vector();
    for(int i=0; i<elements.size(); i++){
      String[] nds = (String[])elements.elementAt(i);
      float[] nd0 = (float[])nodes.get(nds[0]);
      float[] nd1 = (float[])nodes.get(nds[1]);
      float[] nd2 = (float[])nodes.get(nds[2]);
      float[] p = lib3D.PL3T_LINE(new _Point(nd0[0],nd0[1],nd0[2]),new _Point(nd1[0],nd1[1],nd1[2]),new _Point(nd2[0],nd2[1],nd2[2]),new _Point(Float.MIN_VALUE,y,z),new _Point(Float.MAX_VALUE,y,z));
      boolean exist = false;
      for(int j=0; p!=null && j<v.size(); j++){
        if(((Float)v.elementAt(j)).floatValue()==p[0])exist=true;
      }
      if(p!=null && !exist){v.addElement(new Float(p[0]));}
    }
    arr = new float[v.size()];
    if(((int)(arr.length/2))*2==arr.length){
      for(int i=0; i<v.size(); i++){
        arr[i] = ((Float)v.elementAt(i)).floatValue();
      }
      for(int i=0; i<arr.length; i++){
        for(int j=i; j<arr.length; j++){
          if(arr[i]>arr[j]){
            float a=arr[i];
            arr[i]=arr[j];
            arr[j]=a;
          }
        }
      }
      for(int i=0; i<arr.length/2; i++){
        if(arr[i*2]<=x && arr[i*2+1]>=x)return true;
      }
    }else if(arr.length>0)yz=true;
    return (xy && xz && yz);
  }

  public boolean delete(){
    for(int i=0; i<elementsDB.size(); i++){
      if(((_Object)elementsDB.elementAt(i)).isSelected()){
        elementsDB.removeElementAt(i);
        i--;
      }
    }
    for(int i=0; i<nodesDB.size(); i++){
      _Node nd = (_Node)nodesDB.elementAt(i);
      if(nd.isSelected()){
        boolean using = false;
        for(int j=0; j<elementsDB.size(); j++){
          _Node[] nds = ((_Object)elementsDB.elementAt(j)).get_Nodes();
          for(int k=0; k<nds.length; k++){
            if(nds[k].equals(nd))using=true;
          }
        }
        if(!using){
          nodesDB.removeElementAt(i);
          i--;
        }
      }
    }
    return selected;
  }

  public _Stl(String file){
    file_name=file;
    nodesDB.clear();
    elementsDB.clear();
    nodes = new Hashtable();
    elements = new Vector();
    try{
      RandomAccessFile in = new RandomAccessFile(file, "r");
      byte[] b = new byte[80];
      in.read(b,0,80);
      in.close();
      in = new RandomAccessFile(file, "r");
      if(new String(b).indexOf("\n")!=-1){
        //ascii
        String st;
        while((st=in.readLine())!=null){
          StringTokenizer stt = new StringTokenizer(st);
          if(stt.nextToken().equalsIgnoreCase("vertex")){
            float nx,ny,nz;
            String[] el = new String[3];
            nx = Float.parseFloat(stt.nextToken());
            ny = Float.parseFloat(stt.nextToken());
            nz = Float.parseFloat(stt.nextToken());
            el[0]=nx+"_"+ny+"_"+nz;
            nodes.put(el[0],new _Node(nx,ny,nz){ public String get_Id(){ return Id+"."+super.get_Id(); }});
            st=in.readLine();
            stt = new StringTokenizer(st);
            stt.nextToken();
            nx = Float.parseFloat(stt.nextToken());
            ny = Float.parseFloat(stt.nextToken());
            nz = Float.parseFloat(stt.nextToken());
            el[1]=nx+"_"+ny+"_"+nz;
            nodes.put(el[1],new _Node(nx,ny,nz){ public String get_Id(){ return Id+"."+super.get_Id(); }});
            st=in.readLine();
            stt = new StringTokenizer(st);
            stt.nextToken();
            nx = Float.parseFloat(stt.nextToken());
            ny = Float.parseFloat(stt.nextToken());
            nz = Float.parseFloat(stt.nextToken());
            el[2]=nx+"_"+ny+"_"+nz;
            nodes.put(el[2],new _Node(nx,ny,nz){ public String get_Id(){ return Id+"."+super.get_Id(); }});
            elements.addElement(el);
          }
        }
      }else{
        //binary
        in.read(b,0,80);
        b = new byte[4];
        in.read(b,0,4);
        int facets = arr4byte_to_int(b);
        for(int i=0; i<facets; i++){
          String[] el = new String[3];
          float nx,ny,nz;
          in.read(b,0,4);in.read(b,0,4);in.read(b,0,4);
          in.read(b,0,4);
          nx = arr4byte_to_float(b);
          in.read(b,0,4);
          ny = arr4byte_to_float(b);
          in.read(b,0,4);
          nz = arr4byte_to_float(b);
          el[0]=nx+"_"+ny+"_"+nz;
          nodes.put(el[0],new _Node(nx,ny,nz){ public String get_Id(){ return Id+"."+super.get_Id(); }});
          in.read(b,0,4);
          nx = arr4byte_to_float(b);
          in.read(b,0,4);
          ny = arr4byte_to_float(b);
          in.read(b,0,4);
          nz = arr4byte_to_float(b);
          el[1]=nx+"_"+ny+"_"+nz;
          nodes.put(el[1],new _Node(nx,ny,nz){ public String get_Id(){ return Id+"."+super.get_Id(); }});
          in.read(b,0,4);
          nx = arr4byte_to_float(b);
          in.read(b,0,4);
          ny = arr4byte_to_float(b);
          in.read(b,0,4);
          nz = arr4byte_to_float(b);
          el[2]=nx+"_"+ny+"_"+nz;
          nodes.put(el[2],new _Node(nx,ny,nz){ public String get_Id(){ return Id+"."+super.get_Id(); }});
          elements.addElement(el);
          in.readByte();in.readByte();
        }
      }
      in.close();
      System.out.println("Loaded "+file+"\nFacets - "+elements.size());
      System.out.println("Nodes - "+nodes.size());
      
      for(int i=0; i<elements.size(); i++){
        String[] el = (String[])elements.elementAt(i);
        elementsDB.add(new _Element3((_Node)nodes.get(el[0]),(_Node)nodes.get(el[1]),(_Node)nodes.get(el[2]),Canvas3D.MESH_Shell_C0_3,null,1){
          public String get_Id(){ return Id+"."+super.get_Id(); }
        });
      }
      for (Enumeration e = nodes.keys(); e.hasMoreElements();) nodesDB.add(nodes.get(e.nextElement()+""));
      for(int i=0; i<nodesDB.size(); i++) ((_Object)nodesDB.elementAt(i)).set_Id(i+"");
      for(int i=0; i<elementsDB.size(); i++) ((_Object)elementsDB.elementAt(i)).set_Id(i+"");

    }catch(Exception e){ System.out.println(e); e.printStackTrace();}

  }
  private final int arr4byte_to_int(byte[] b){
    int res = 0;
    for(int i=0; i<4; i++){
      res|=(b[i] & 0xff)<<(i*8);
    }
    return res;
  }
  private final float arr4byte_to_float(byte[] b){
    int res = 0;
    for(int i=0; i<4; i++){
      res|=(b[i] & 0xff)<<(i*8);
    }
    return Float.intBitsToFloat(res);
  }
  public Object[] get_Array(Canvas3D j3d){
      arr = new Vector();
      Object[] shparr;
      
      // Generate nodes
      for(int i=0; i<nodesDB.size(); i++){
        _Node nd = (_Node)nodesDB.elementAt(i);

        shparr = nd.get_Array(j3d);
        for (int j=0; j<shparr.length; j++)
            arr.add(shparr[j]);
      }

      // Generate elements
      for(int i=0; i<elementsDB.size(); i++){
        _Object el = (_Object)elementsDB.elementAt(i);
        shparr = el.get_Array(j3d);
        for (int j=0; j<shparr.length; j++)
            arr.add(shparr[j]);
      }
      
      return arr.toArray();
  }

  public boolean isSelected(){return selected;}

  public void Select(String st){
    selected=st!=null;
    if(st==null){
      for(int i=0; i<nodesDB.size(); i++) ((_Node)nodesDB.elementAt(i)).Select(st);
      for(int i=0; i<elementsDB.size(); i++) ((_Object)elementsDB.elementAt(i)).Select(st);
    }
  }

  public void addSelectedObjects(Vector v) {
      if (selected) v.add(this);
      for(int i=0; i<nodesDB.size(); i++) ((_Node)nodesDB.elementAt(i)).addSelectedObjects(v);
      for(int i=0; i<elementsDB.size(); i++) ((_Object)elementsDB.elementAt(i)).addSelectedObjects(v);
 }
  
  
  public String toString(){ return "Stl ID="+Id;}

  public MutableTreeNode get_TreeNode(){
    DefaultMutableTreeNode node = new DefaultMutableTreeNode(this);
    DefaultMutableTreeNode n_nodes = new DefaultMutableTreeNode("Nodes");
    DefaultMutableTreeNode n_elements = new DefaultMutableTreeNode("Elements");
    node.add(new DefaultMutableTreeNode(file_name));
    for(int i=0; i<nodesDB.size(); i++) n_nodes.add(((_Object)nodesDB.elementAt(i)).get_TreeNode());
    for(int i=0; i<elementsDB.size(); i++) n_elements.add(((_Object)elementsDB.elementAt(i)).get_TreeNode());
    node.add(n_nodes);
    node.add(n_elements);
    return node;
  }

  public void transform3D(Matrix3D t){
    if (!selected  || processed) return;
    for(int i=0; i<nodesDB.size(); i++){
      _Node nd = (_Node)nodesDB.elementAt(i);
      if(nd.isSelected()){
        nd.transform3D(t);
        nd.Select(null);
      }
    }
  }

  public JPanel getEditPanel(Canvas3D j3d, PreProcessor pp){ return new JPanel(); }

  public _Node[] get_Nodes(){
    _Node[] arr = new _Node[nodesDB.size()];
    for(int i=0; i<nodesDB.size(); i++) arr[i] = (_Node)nodesDB.elementAt(i);
    return arr;
  }

  public _Object[] get_Elements(){
    _Object[] arr = new _Object[elementsDB.size()];
    for(int i=0; i<elementsDB.size(); i++) arr[i] = (_Object)elementsDB.elementAt(i);
    return arr;
  }

  public _Object duplicate(Canvas3D out,boolean add){ 
      _Stl o = null;
      try {
        o = (_Stl)this.clone();
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    
    if (add) out.add3D(o);
    
    return o; 
      }
  
  public boolean isPickPoint(int x, int y, boolean shw) {
      boolean check = false;
      _Node nd;
      _Object el;
      
/*      if (show == shw)
      for (int i=0; i< arr.length; i++) 
      	check = (((shp)arr[i]).isPickPoint(x,y) == true ? true : check);
*/
      // Check nodes
      for(int i=0; i<nodesDB.size(); i++)
          {
              nd = (_Node)nodesDB.elementAt(i);
              if (nd.isPickPoint(x,y,shw)) nd.Select("");
          }
      
      // Check elements
      for(int i=0; i<elementsDB.size(); i++)
          {
              el = (_Object)elementsDB.elementAt(i);
              if (el.isPickPoint(x,y,shw)) el.Select("");
          }
      
      
      return check;
  }
  
public boolean isPickPoint(Rectangle2D r, boolean shw) {
      boolean check = false;
      _Node nd;
      _Object el;
/*      
      if (show == shw)
      for (int i=0; i< arr.length; i++) 
      	check = (((shp)arr[i]).isPickPoint(r) == true ? true : check);
*/
      // Check nodes
      for(int i=0; i<nodesDB.size(); i++)
          {
              nd = (_Node)nodesDB.elementAt(i);
              if (nd.isPickPoint(r,shw)) nd.Select("");
          }
      
      // Check elements
      for(int i=0; i<elementsDB.size(); i++)
          {
              el = (_Object)elementsDB.elementAt(i);
              if (el.isPickPoint(r,shw)) el.Select("");
          }
      
      
      return check;
  }

public void setShow(boolean s) {
    _Node nd;
    _Object el;
    
    // Check nodes
    for(int i=0; i<nodesDB.size(); i++)
        {
            nd = (_Node)nodesDB.elementAt(i);
            if (nd.isSelected()) nd.setShow(s);
        }
    
    // Check elements
    for(int i=0; i<elementsDB.size(); i++)
        {
            el = (_Object)elementsDB.elementAt(i);
            if (el.isSelected()) el.setShow(s);
        }
    
    show = s;
}


}