Skip to content
Snippets Groups Projects
STL_particles.cpp 7.98 KiB
Newer Older
//
// 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;
   }