Skip to content
Snippets Groups Projects
STL_particles.cpp 7.98 KiB
Newer Older
  • Learn to ignore specific revisions
  • //
    // STL_particles.cpp
    
    Amira Abdel-Rahman (admin)'s avatar
    Amira Abdel-Rahman (admin) committed
    //    input STL, output particles, FCC lattice
    
    //    (c) MIT CBA Neil Gershenfeld 6/4/20
    
    Amira Abdel-Rahman (admin)'s avatar
    Amira Abdel-Rahman (admin) committed
    // todo
    //    test need for perturbation
    
    //
    // includes
    //
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    
    Amira Abdel-Rahman (admin)'s avatar
    Amira Abdel-Rahman (admin) committed
    #include <cstring>
    
    
    using namespace std;
    //
    // variables
    //
    float xmin,xmax,ymin,ymax,zmin,zmax,d;
    float *ax[3],*ay[3],*az[3],*sx[2],*sy[2];
    //
    // coordinate functions
    //
    float xpos(int x,int y,int z) {
       float dx;
       if (y%2 == 0) {
          if (z%3 == 0) dx = 0;
          else if (z%3 == 1) dx = 0.5;
          else dx = 0;
          }
       else {
          if (z%3 == 0) dx = 0;
          else if (z%3 == 1) dx = -0.5;
          else dx = 0;
          }
       return xmin+(x+(y%2)/2.0+dx)*d;
       }
    float ypos(int y,int z) {
       float dy;
       if (z%3 == 0) dy = 0;
       else if (z%3 == 1) dy = 1/(2*sqrt(3));
       else dy = 1/sqrt(3);
       return ymin+(sqrt(3.0)*y/2.0+dy)*d;
       }
    float zpos(int z) {
       return zmin+(sqrt(2.0/3.0)*z)*d;
       }
    //
    // main
    //
    int main(int argc, char** argv) {
    
    Amira Abdel-Rahman (admin)'s avatar
    Amira Abdel-Rahman (admin) committed
       if (argc == 1) {
          cerr << "command line: STL_particles [arguments] < input.stl | particle sink " << endl;
          cerr << "   nlattice=(lattice size between x limits)" << endl;
    
          return 1;
          }
    
    Amira Abdel-Rahman (admin)'s avatar
    Amira Abdel-Rahman (admin) committed
       int nlattice;
       if (nullptr == strstr(argv[1],"nlattice=")) {
          cerr << "STL_particles argument not recognized" << endl;
          return 1;
          }
       else
          nlattice = stoi(argv[1]+9);
    
       //
       // read number of triangles
       //
       int ntriangles;
       cin.seekg(80);
       cin.read((char*)&ntriangles,4);
       cerr << "STL_particles:" << endl;
       cerr << "   input " << ntriangles << " triangles" << endl;
       //
       // read triangles
       //
       ax[0] = new float[ntriangles];
       ax[1] = new float[ntriangles];
       ax[2] = new float[ntriangles];
       ay[0] = new float[ntriangles];
       ay[1] = new float[ntriangles];
       ay[2] = new float[ntriangles];
       az[0] = new float[ntriangles];
       az[1] = new float[ntriangles];
       az[2] = new float[ntriangles];
       sx[0] = new float[ntriangles];
       sx[1] = new float[ntriangles];
       sy[0] = new float[ntriangles];
       sy[1] = new float[ntriangles];
       xmin = 1e10; xmax = -1e10;
       ymin = 1e10; ymax = -1e10;
       zmin = 1e10; zmax = -1e10;
       float x0,y0,z0,x1,y1,z1,x2,y2,z2;
       float p = 1e-6; // perturbation to remove deneracies
       for (int t = 0; t < ntriangles; ++t) {
          //
          // skip normal
          //
          cin.seekg(3*4,ios::cur);
          //
          // read vertices
          //
          cin.read((char*)&x0,4);
          x0 += p;
          if (x0 > xmax) xmax = x0;
          if (x0 < xmin) xmin = x0;
          cin.read((char*)&y0,4);
          y0 += p;
          if (y0 > ymax) ymax = y0;
          if (y0 < ymin) ymin = y0;
          cin.read((char*)&z0,4);
          z0 += p;
          if (z0 > zmax) zmax = z0;
          if (z0 < zmin) zmin = z0;
          cin.read((char*)&x1,4);
          x1 += p;
          if (x1 > xmax) xmax = x1;
          if (x1 < xmin) xmin = x1;
          cin.read((char*)&y1,4);
          y1 += p;
          if (y1 > ymax) ymax = y1;
          if (y1 < ymin) ymin = y1;
          cin.read((char*)&z1,4);
          z1 += p;
          if (z1 > zmax) zmax = z1;
          if (z1 < zmin) zmin = z1;
          cin.read((char*)&x2,4);
          x2 += p;
          if (x2 > xmax) xmax = x2;
          if (x2 < xmin) xmin = x2;
          cin.read((char*)&y2,4);
          y2 += p;
          if (y2 > ymax) ymax = y2;
          if (y2 < ymin) ymin = y2;
          cin.read((char*)&z2,4);
          z2 += p;
          if (z2 > zmax) zmax = z2;
          if (z2 < zmin) zmin = z2;
          //
          // skip attribute
          //
          cin.seekg(2,ios::cur);
          //
          // sort by z and save
          //
          int i0,i1,i2;
          if ((z2 >= z1) && (z2 >= z0))
             if (z1 >= z0) {i0 = 0; i1 = 1; i2 = 2;}
             else {i0 = 1; i1 = 0; i2 = 2;}
          else if ((z1 >= z2) && (z1 >= z0))
             if (z2 >= z0) {i0 = 0; i1 = 2; i2 = 1;}
             else {i0 = 1; i1 = 2; i2 = 0;}
          else
             if (z2 >= z1) {i0 = 2; i1 = 0; i2 = 1;}
             else {i0 = 2; i1 = 1; i2 = 0;}
          ax[i0][t] = x0; ay[i0][t] = y0; az[i0][t] = z0;
          ax[i1][t] = x1; ay[i1][t] = y1; az[i1][t] = z1;
          ax[i2][t] = x2; ay[i2][t] = y2; az[i2][t] = z2;
          }
       cerr << "   xmin/max: " << xmin << ' ' << xmax << endl;
       cerr << "   ymin/max: " << ymin << ' ' << ymax << endl;
       cerr << "   zmin/max: " << zmin << ' ' << zmax << endl;
       d = (xmax-xmin)/(nlattice-1.0);
       int nx = nlattice;
       int ny = (ymax-ymin)/(d*sqrt(3.0)/2.0);
       int nz = (zmax-zmin)/(d*sqrt(2.0/3.0));
       //
       // loop over z slices
       //
       vector<float> xcross,px,py,pz;
       int nsegments;
       for (int iz = 0; iz < nz; ++iz) {
          float z = zpos(iz);
          //
          // loop over triangles to find slice crossings
          //
          nsegments = 0;
          for (int t = 0; t < ntriangles; ++t) {
             if ((az[2][t] > z) && (az[0][t] < z)) {
                //
                // crossing found, check side
                //
                if (az[1][t] > z) {
                   float f10 = (z-az[0][t])/(az[1][t]-az[0][t]);
                   x0 = ax[0][t]+f10*(ax[1][t]-ax[0][t]);
                   y0 = ay[0][t]+f10*(ay[1][t]-ay[0][t]);
                   }
                else {
                   float f21 = (z-az[1][t])/(az[2][t]-az[1][t]);
                   x0 = ax[1][t]+f21*(ax[2][t]-ax[1][t]);
                   y0 = ay[1][t]+f21*(ay[2][t]-ay[1][t]);
                   }
                float f20 = (z-az[0][t])/(az[2][t]-az[0][t]);
                x1 = ax[0][t]+f20*(ax[2][t]-ax[0][t]);
                y1 = ay[0][t]+f20*(ay[2][t]-ay[0][t]);
                //
                // sort y and save segment
                //
                if (y1 >= y0) {
                   sx[0][nsegments] = x0; sy[0][nsegments] = y0;
                   sx[1][nsegments] = x1; sy[1][nsegments] = y1;
                   }
                else {
                   sx[0][nsegments] = x1; sy[0][nsegments] = y1;
                   sx[1][nsegments] = x0; sy[1][nsegments] = y0;
                   }
                ++nsegments;
                }
             }
          //
          // loop over slice rows
          //
          for (int iy = 0; iy < ny; ++iy) {
             float y = ypos(iy,iz);
             //
             // loop over slice segments to find crossings
             //
             for (int s = 0; s < nsegments; ++s)
                if ((sy[1][s] >= y) && (sy[0][s] < y)) {
                   float f = (y-sy[0][s])/(sy[1][s]-sy[0][s]);
                   x0 = sx[0][s]+f*(sx[1][s]-sx[0][s]);
                   xcross.push_back(x0);
                   }
             //
             // sort crossings
             //
             sort(xcross.begin(),xcross.end());
             //
             // loop over slice columns
             //
             int pointer = 0;
             bool inside = false;
             for (int ix = 0; ix < nx; ++ix) {
                if (xcross.size() > 0) {
                   float x = xpos(ix,iy,iz);
                   if (x > xcross[pointer]) {
                      //
                      // passed pointer, toggle side
                      //
                      inside = !inside;
                      ++pointer;
                      if (pointer == xcross.size())
                         break;
                      }
                   if (inside) {
                      //
                      // inside, save point
                      //
                      px.push_back(x);
                      py.push_back(y);
                      pz.push_back(z);
                      }
                   }
                }
             xcross.clear();
             }
          }
       int number = px.size();
       cerr << "   output " << number << " particles" << endl;
       //
       // output particles
       //
       cout << "type:" << endl;
       cout << "FCC" << endl;
       cout << "format:" << endl;
       cout << "xyz float32" << endl;
       cout << "xmin:" << endl;
       cout << xmin << endl;
       cout << "xmax:" << endl;
       cout << xmax << endl;
       cout << "ymin:" << endl;
       cout << ymin << endl;
       cout << "ymax:" << endl;
       cout << ymax << endl;
       cout << "zmin:" << endl;
       cout << zmin << endl;
       cout << "zmax:" << endl;
       cout << zmax << endl;
       cout << "links per particle:" << endl;
       cout << 12 << endl;
       cout << "number:" << endl;
       cout << number << endl;
       cout << "pitch:" << endl;
       cout << d << endl;
       cout << "particles:" << endl;
       for (int i = 0; i < number; ++i) {
          cout.write((char*)&px[i],4);
          cout.write((char*)&py[i],4);
          cout.write((char*)&pz[i],4);
          }
       cout << "end:" << endl;
       }