Beispiel #1
0
void Output<Integer>::write_files() const {
    const Sublattice_Representation<Integer>& BasisChange = Result->getSublattice();
    size_t i, nr;
    const Matrix<Integer>& Generators = Result->getGeneratorsMatrix();
    const Matrix<Integer>& Support_Hyperplanes = Result->getSupportHyperplanesMatrix();
    vector<libnormaliz::key_t> rees_ideal_key;

    if (esp && Result->isComputed(ConeProperty::SupportHyperplanes)) {
        //write the suport hyperplanes of the full dimensional cone
        Matrix<Integer> Support_Hyperplanes_Full_Cone = BasisChange.to_sublattice_dual(Support_Hyperplanes);
        // Support_Hyperplanes_Full_Cone.print(name,"esp");
        string esp_string = name+".esp";
        const char* esp_file = esp_string.c_str();
        ofstream esp_out(esp_file);
        Support_Hyperplanes_Full_Cone.print(esp_out);
        esp_out << "inequalities" << endl;
        if (Result->isComputed(ConeProperty::Grading)) {
            esp_out << 1 << endl << rank << endl;
            esp_out << BasisChange.to_sublattice_dual(Result->getGrading());
            esp_out << "grading" << endl;
        }
        if (Result->isComputed(ConeProperty::Dehomogenization)) {
            esp_out << 1 << endl << rank << endl;
            esp_out << BasisChange.to_sublattice_dual(Result->getDehomogenization());
            esp_out << "dehomogenization" << endl;
        }
        esp_out.close();
    }
    if (tgn)
        Generators.print(name,"tgn");
    if (tri && Result->isComputed(ConeProperty::Triangulation)) {     //write triangulation
        write_tri();
    }

    if (out==true) {  //printing .out file
        string name_open=name+".out";                              //preparing output files
        const char* file=name_open.c_str();
        ofstream out(file);

        // write "header" of the .out file
        size_t nr_orig_gens = 0;
        if (lattice_ideal_input) {
            nr_orig_gens = Result->getNrOriginalMonoidGenerators();
            out << nr_orig_gens <<" original generators of the toric ring"<<endl;
        }
        if (Result->isComputed(ConeProperty::ModuleGenerators)) {
            out << Result->getNrModuleGenerators() <<" module generators" << endl;
        }
        if (Result->isComputed(ConeProperty::HilbertBasis)) {
            out << Result->getNrHilbertBasis() <<" Hilbert basis elements"
                << of_monoid << endl;
        }
        if (homogeneous && Result->isComputed(ConeProperty::Deg1Elements)) {
            out << Result->getNrDeg1Elements() <<" Hilbert basis elements of degree 1"<<endl;
        }
        if (Result->isComputed(ConeProperty::IsReesPrimary)
            && Result->isComputed(ConeProperty::HilbertBasis)) {
            const Matrix<Integer>& Hilbert_Basis = Result->getHilbertBasisMatrix();
            nr = Hilbert_Basis.nr_of_rows();
            for (i = 0; i < nr; i++) {
                if (Hilbert_Basis.read(i,dim-1)==1) {
                    rees_ideal_key.push_back(i);
                 }
            }
            out << rees_ideal_key.size() <<" generators of integral closure of the ideal"<<endl;
        }
        if (Result->isComputed(ConeProperty::VerticesOfPolyhedron)) {
            out << Result->getNrVerticesOfPolyhedron() <<" vertices of polyhedron" << endl;
        }
        if (Result->isComputed(ConeProperty::ExtremeRays)) {
            out << Result->getNrExtremeRays() <<" extreme rays" << of_cone << endl;
        }
        if(Result->isComputed(ConeProperty::ModuleGeneratorsOverOriginalMonoid)) {
            out << Result->getNrModuleGeneratorsOverOriginalMonoid() <<" module generators over original monoid" << endl;    
        }
        if (Result->isComputed(ConeProperty::SupportHyperplanes)) {
            out << Result->getNrSupportHyperplanes() <<" support hyperplanes"
                << of_polyhedron << endl;
        }
        out<<endl;
        if (Result->isComputed(ConeProperty::ExcludedFaces)) {
            out << Result->getNrExcludedFaces() <<" excluded faces"<<endl;
            out << endl;
        }
        out << "embedding dimension = " << dim << endl;
        if (homogeneous) {
            out << "rank = "<< rank << is_maximal(rank,dim) << endl;
            //out << "index E:G = "<< BasisChange.get_index() << endl;
            out << "external index = "<< BasisChange.getExternalIndex() << endl;
        } else { // now inhomogeneous case
            if (Result->isComputed(ConeProperty::AffineDim))
                out << "affine dimension of the polyhedron = "
                    << Result->getAffineDim() << is_maximal(Result->getAffineDim(),dim-1) << endl;
            if (Result->isComputed(ConeProperty::RecessionRank))
                out << "rank of recession monoid = "  << Result->getRecessionRank() << endl;
        }
        
        if(Result->isComputed(ConeProperty::OriginalMonoidGenerators)){
            out << "internal index = " << Result->getIndex() << endl;           
        }
        
        if (homogeneous && Result->isComputed(ConeProperty::IsIntegrallyClosed)) {
            if (Result->isIntegrallyClosed()) {
                out << "original monoid is integrally closed"<<endl;
            } else {
                out << "original monoid is not integrally closed"<<endl;
            }
        }
        out << endl;
        if (Result->isComputed(ConeProperty::TriangulationSize)) {
            out << "size of ";
            if (Result->isTriangulationNested()) out << "nested ";
            if (Result->isTriangulationPartial()) out << "partial ";
            out << "triangulation   = " << Result->getTriangulationSize() << endl;
        }
        if (Result->isComputed(ConeProperty::TriangulationDetSum)) {
            out << "resulting sum of |det|s = " << Result->getTriangulationDetSum() << endl;
        }
        if (Result->isComputed(ConeProperty::TriangulationSize)) {
            out << endl;
        }
        if ( Result->isComputed(ConeProperty::Dehomogenization) ) {
            out << "dehomogenization:" << endl
                << Result->getDehomogenization() << endl;
        }
        if ( Result->isComputed(ConeProperty::Grading) ) {
            out << "grading:" << endl
                << Result->getGrading();
            Integer denom = Result->getGradingDenom();
            if (denom != 1) {
                out << "with denominator = " << denom << endl;
            }
            out << endl;
            if (homogeneous && Result->isComputed(ConeProperty::ExtremeRays)) {
                out << "degrees of extreme rays:"<<endl;
                map<Integer,long> deg_count;
                vector<Integer> degs = Result->getExtremeRaysMatrix().MxV(Result->getGrading());
                for (i=0; i<degs.size(); ++i) {
                    deg_count[degs[i]/denom]++;
                }
                out << deg_count;
            }
        }
        else if (Result->isComputed(ConeProperty::IsDeg1ExtremeRays)) {
            if ( !Result->isDeg1ExtremeRays() ) {
                out << "No implicit grading found" << endl;
            }
        }
        out<<endl;
        if (homogeneous && Result->isComputed(ConeProperty::IsDeg1HilbertBasis)
          && Result->isDeg1ExtremeRays() ) {
            if (Result->isDeg1HilbertBasis()) {
                out << "Hilbert basis elements are of degree 1";
            } else {
                out << "Hilbert basis elements are not of degree 1";
            }
            out<<endl<<endl;
        }
        if ( Result->isComputed(ConeProperty::ModuleRank) ) {
            out << "module rank = "<< Result->getModuleRank() << endl;
        }
        if ( Result->isComputed(ConeProperty::Multiplicity) ) {
            out << "multiplicity = "<< Result->getMultiplicity() << endl;
        }
        if ( Result->isComputed(ConeProperty::ModuleRank) || Result->isComputed(ConeProperty::Multiplicity)) {
            out << endl;
        }
        
        if ( Result->isComputed(ConeProperty::HilbertSeries) ) {
            const HilbertSeries& HS = Result->getHilbertSeries();
            out << "Hilbert series:" << endl << HS.getNum();
            map<long, long> HS_Denom = HS.getDenom();
            long nr_factors = 0;
            for (map<long, long>::iterator it = HS_Denom.begin(); it!=HS_Denom.end(); ++it) {
                nr_factors += it->second;
            }
            out << "denominator with " << nr_factors << " factors:" << endl;
            out << HS.getDenom();
            out << endl;
            if (HS.getShift() != 0) {
                out << "shift = " << HS.getShift() << endl << endl;
            }
            out << "degree of Hilbert Series as rational function = "
                << HS.getDegreeAsRationalFunction() << endl << endl;

            long period = HS.getPeriod();
            if (period == 1) {
                out << "Hilbert polynomial:" << endl;
                out << HS.getHilbertQuasiPolynomial()[0];
                out << "with common denominator = ";
                out << HS.getHilbertQuasiPolynomialDenom();
                out << endl<< endl;
            } else {
                // output cyclonomic representation
                out << "Hilbert series with cyclotomic denominator:" << endl;
                out << HS.getCyclotomicNum();
                out << "cyclotomic denominator:" << endl;
                out << HS.getCyclotomicDenom();
                out << endl;
                // Hilbert quasi-polynomial
                HS.computeHilbertQuasiPolynomial();
                if (HS.isHilbertQuasiPolynomialComputed()) {
                    out<<"Hilbert quasi-polynomial of period " << period << ":" << endl;
                    Matrix<mpz_class> HQP(HS.getHilbertQuasiPolynomial());
                    HQP.pretty_print(out,true);
                    out<<"with common denominator = "<<HS.getHilbertQuasiPolynomialDenom();
                }
                out << endl << endl;
            }

        }

        if (Result->isComputed(ConeProperty::IsReesPrimary)) {
            if (Result->isReesPrimary()) {
                out<<"ideal is primary to the ideal generated by the indeterminates"<<endl;
            } else {
                out<<"ideal is not primary to the ideal generated by the indeterminates"<<endl;
            }
            if (Result->isComputed(ConeProperty::ReesPrimaryMultiplicity)) {
                out<<"multiplicity of the ideal = "<<Result->getReesPrimaryMultiplicity()<<endl;
            }
            out << endl;
        }
        
        if(Result->isComputed(ConeProperty::ClassGroup)) {
            vector<Integer> ClassGroup=Result->getClassGroup();
            out << "rank of class group = " << ClassGroup[0] << endl;
            if(ClassGroup.size()==1)
                out << "class group is free" << endl << endl;
            else{
                ClassGroup.erase(ClassGroup.begin());
                out << "finite cyclic summands:" << endl;
                out << count_in_map<Integer,size_t>(ClassGroup);
                out << endl;
            }                   
        }

        out << "***********************************************************************"
            << endl << endl;


        if (lattice_ideal_input) {
            out << nr_orig_gens <<" original generators:"<<endl;
            Result->getOriginalMonoidGeneratorsMatrix().pretty_print(out);
            out << endl;
        }
        if (Result->isComputed(ConeProperty::ModuleGenerators)) {
            out << Result->getNrModuleGenerators() <<" module generators:" << endl;
            Result->getModuleGeneratorsMatrix().pretty_print(out);
            out << endl;
        }
        
        if ( Result->isComputed(ConeProperty::Deg1Elements) ) {
            const Matrix<Integer>& Hom = Result->getDeg1ElementsMatrix();
            write_matrix_ht1(Hom);
            nr=Hom.nr_of_rows();
            out<<nr<<" Hilbert basis elements of degree 1:"<<endl;
            Hom.pretty_print(out);
            out << endl;
        }
        
        if (Result->isComputed(ConeProperty::HilbertBasis)) {

            const Matrix<Integer>& Hilbert_Basis = Result->getHilbertBasisMatrix();
            
            if(!Result->isComputed(ConeProperty::Deg1Elements)){
                nr=Hilbert_Basis.nr_of_rows();
                out << nr << " Hilbert basis elements" << of_monoid << ":" << endl;
                Hilbert_Basis.pretty_print(out);
                out << endl;
            }
            else {
                nr=Hilbert_Basis.nr_of_rows()-Result->getNrDeg1Elements();
                out << nr << " further Hilbert basis elements" << of_monoid << " of higher degree:" << endl;
                Matrix<Integer> HighDeg(nr,dim);
                for(size_t i=0;i<nr;++i)
                    HighDeg[i]=Hilbert_Basis[i+Result->getNrDeg1Elements()];                               
                HighDeg.pretty_print(out);
                out << endl;                       
            }
            Matrix<Integer> complete_Hilbert_Basis(0,dim);
            if (gen || egn || typ) {
                // for these files we append the module generators if there are any
                if (Result->isComputed(ConeProperty::ModuleGenerators)) {
                    complete_Hilbert_Basis.append(Hilbert_Basis);
                    complete_Hilbert_Basis.append(Result->getModuleGeneratorsMatrix());
                    write_matrix_gen(complete_Hilbert_Basis);
                } else {
                    write_matrix_gen(Hilbert_Basis);
                }                
            }
            if (egn || typ) {
                Matrix<Integer> Hilbert_Basis_Full_Cone = BasisChange.to_sublattice(Hilbert_Basis);
                if (Result->isComputed(ConeProperty::ModuleGenerators)) {
                    Hilbert_Basis_Full_Cone.append(BasisChange.to_sublattice(Result->getModuleGeneratorsMatrix()));
                }
                if (egn) {
                    string egn_string = name+".egn";
                    const char* egn_file = egn_string.c_str();
                    ofstream egn_out(egn_file);        
                    Hilbert_Basis_Full_Cone.print(egn_out);
                    // egn_out<<"cone"<<endl;
                    egn_out.close();
                }    

                if (typ && homogeneous) {
                    write_matrix_typ(Hilbert_Basis_Full_Cone.multiplication(BasisChange.to_sublattice_dual(Support_Hyperplanes).transpose()));
                }
            }

            if (Result->isComputed(ConeProperty::IsReesPrimary)) {
                out << rees_ideal_key.size() <<" generators of integral closure of the ideal:"<<endl;
                Matrix<Integer> Ideal_Gens = Hilbert_Basis.submatrix(rees_ideal_key);
                Ideal_Gens.resize_columns(dim-1);
                Ideal_Gens.pretty_print(out);
                out << endl;
            }
        }
        if (Result->isComputed(ConeProperty::VerticesOfPolyhedron)) {
            out << Result->getNrVerticesOfPolyhedron() <<" vertices of polyhedron:" << endl;
            Result->getVerticesOfPolyhedronMatrix().pretty_print(out);
            out << endl;
        }
        if (Result->isComputed(ConeProperty::ExtremeRays)) {
            out << Result->getNrExtremeRays() << " extreme rays" << of_cone << ":" << endl;
            Result->getExtremeRaysMatrix().pretty_print(out);
            out << endl;
            if (ext) {
                // for the .gen file we append the vertices of polyhedron if there are any
                if (Result->isComputed(ConeProperty::VerticesOfPolyhedron)) {
                    Matrix<Integer> Extreme_Rays(Result->getExtremeRaysMatrix());
                    Extreme_Rays.append(Result->getVerticesOfPolyhedronMatrix());
                    write_matrix_ext(Extreme_Rays);
                } else {
                    write_matrix_ext(Result->getExtremeRaysMatrix());
                }
            }
        }
        
        if(Result->isComputed(ConeProperty::ModuleGeneratorsOverOriginalMonoid)) {
            out << Result->getNrModuleGeneratorsOverOriginalMonoid() <<" module generators over original monoid:" << endl;
            Result->getModuleGeneratorsOverOriginalMonoidMatrix().pretty_print(out);
            out << endl;
            if(mod)
                write_matrix_mod(Result->getModuleGeneratorsOverOriginalMonoidMatrix());
        }

        //write constrains (support hyperplanes, congruences, equations)

        if (Result->isComputed(ConeProperty::SupportHyperplanes)) {
            out << Support_Hyperplanes.nr_of_rows() <<" support hyperplanes" 
                << of_polyhedron << ":" << endl;
            Support_Hyperplanes.pretty_print(out);
            out << endl;
        }
        if (Result->isComputed(ConeProperty::ExtremeRays)) {
            //equations
            const Matrix<Integer>& Equations = BasisChange.getEquationsMatrix();
            size_t nr_of_equ = Equations.nr_of_rows();
            if (nr_of_equ > 0) {
                out << nr_of_equ <<" equations:" <<endl;
                Equations.pretty_print(out);
                out << endl;
            }

            //congruences
            const Matrix<Integer>& Congruences = BasisChange.getCongruencesMatrix();
            size_t nr_of_cong = Congruences.nr_of_rows();
            if (nr_of_cong > 0) {
                out << nr_of_cong <<" congruences:" <<endl;
                Congruences.pretty_print(out);
                out << endl;
            }
            
            //lattice
            const Matrix<Integer>& LatticeBasis = BasisChange.getEmbeddingMatrix();
            size_t nr_of_latt = LatticeBasis.nr_of_rows();
            if (nr_of_latt < dim ||  BasisChange.getExternalIndex()!=1) {
                out << nr_of_latt <<" basis elements of lattice:" <<endl;
                LatticeBasis.pretty_print(out);
                out << endl;
            }
            if(lat)
                write_matrix_lat(LatticeBasis);
            

            //excluded faces
            if (Result->isComputed(ConeProperty::ExcludedFaces)) {
                const Matrix<Integer>& ExFaces = Result->getExcludedFacesMatrix();
                out << ExFaces.nr_of_rows() <<" excluded faces:" <<endl;
                ExFaces.pretty_print(out);
                out << endl;
            }

            if(cst) {
                string cst_string = name+".cst";
                const char* cst_file = cst_string.c_str();
                ofstream cst_out(cst_file);
    
                Support_Hyperplanes.print(cst_out);
                cst_out<<"inequalities"<<endl;
                Equations.print(cst_out);
                cst_out<<"equations"<<endl;
                Congruences.print(cst_out);
                cst_out<<"congruences"<<endl;
                if (Result->isComputed(ConeProperty::ExcludedFaces)) {
                    Result->getExcludedFacesMatrix().print(cst_out);
                    cst_out<<"excluded_faces"<<endl;
                }
                if (Result->isComputed(ConeProperty::Grading)) {
                    cst_out << 1 << endl << dim << endl;
                    cst_out << Result->getGrading();
                    cst_out << "grading" << endl;
                }
                if (Result->isComputed(ConeProperty::Dehomogenization)) {
                    cst_out << 1 << endl << dim << endl;
                    cst_out << Result->getDehomogenization();
                    cst_out << "dehomogenization" << endl;
                }
                cst_out.close();
            }
        }
        
        out.close();
    }

    write_inv_file();
    write_Stanley_dec();
}
Beispiel #2
0
int main(int argc, char** argv) {
    if(argc >= 2) {
        if(strcmp(argv[1], "--help") == 0) {
            print_usage();
            exit(2);
        }
    }
    int c;
    int errflg = 0;

    int male = 1;
    float D = 9.0;        // default value, can be changed as a command line argument
    float P = 2;          // default value, can be changed as a command line argument
    float theta = M_PI/3; // 60 degrees, the standard, can be changed as a command line argument

    float screwHeight = 20; // height of entire screw (without a head)
                            // TODO maybe add ability to add a head
    float outerDiameter = -1;

    int segments = 72; // number of segments to approximate a circle, 
                        // higher the number, higher the resolution 
                        // (and file size) of the stl file

    while((c = getopt(argc, argv, "fP:D:a:h:s:o:")) != -1) {
        switch(c) {
            case 'f':
                male = 0;
                break;
            case 'P':
                P = atof(optarg);
                break;
            case 'D':
                D = atof(optarg);
                break;
            case 'a':
                theta = atof(optarg)*M_PI/180;
                break;
            case 'h':
                screwHeight = atof(optarg);
                break;
            case 's':
                segments = atoi(optarg);
                break;
            case 'o':
                outerDiameter = atof(optarg);
                break;
            case '?':
                fprintf(stderr, "Unrecognized option: '-%c'\n", optopt);
                errflg++;
                break;
        }
    }

    if(outerDiameter <= D) {
        outerDiameter = D+1;
    }

    if(errflg || optind >= argc) {
        print_usage();
        exit(2);
    }

    char *file = argv[optind];

    FILE *outf;

    outf = fopen(file, "wb");
    if(!outf) {
        fprintf(stderr, "Can't write to file: %s\n", file);
        exit(2);
    }

    char header[81] = {0};
    // TODO add some settings summary to header string
    snprintf(header, 81, "Created with stl_threads.");

    fwrite(header, 80, 1, outf);

    // writing 0 to num_tris for now, will update it at the end.
    uint32_t num_tris = 0;
    fwrite(&num_tris, 4, 1, outf);

    // ISO metric screw thread standard designates screw threads 
    // as M followed by diameter D, a multiplication sign, and then 
    // the pitch P (e.g. M8x1.25). Other standards designate standard
    // pitches for a given diameter (e.g. M8 means the same as M8x1.25).
    //
    // See http://en.wikipedia.org/wiki/ISO_metric_screw_thread
    //
    // The standard assumes a theta of 60 degrees, but we allow
    // theta to change, for ease of manufacturing. Certain 3D printers
    // may not be able to print without drooping at 60 degrees.

    int female = !male;

    // equations vary from wikipedia because we're not assuming a 60 degree theta
    // and we're allowing cutting off different amounts than H/8
    // and H/4 from the tip and troughs

    float tantheta_2 = tan(theta/2);
    float H = P/(2*tantheta_2); 
    float Htip = H/8;
    float Htrough = H/4;
    float Hdiff = H-Htip-Htrough;

    float Pdiff = Hdiff*tantheta_2;
    float Ptip = 2*Htip*tantheta_2;
    float Ptrough = 2*Htrough*tantheta_2;

    float Dmin = D-2*Hdiff;
    float Dmin_2 = Dmin/2;
    float D_2 = D/2;
    float fD = outerDiameter/2;


    /*
    // my ascii representation of image at 
    // (http://en.wikipedia.org/wiki/ISO_metric_screw_thread)
    // with my own added variables
    
                |<--H->|
                |      |
    |           |      |
    |-------------. pt5|   ------   // pt5 is the same as pt1 one cycle later
    |    ^      |/|    |      ^
    |    |      . |    |     Ptrough
    |    |       \|    |      v
    |    |        . pt4|   ------
    |    |         \   |
    |    |        ( \  |
    |            (   . pt3  ------
    |    P      (    |\        ^
    |          theta | .       Ptip
    |    |      (    |/        v
    |    |       (   . pt2  ------
    |    |        ( /          ^
    |    v         / |         Pdiff
    |-------------. pt1     ------ 
    |            /|  |
    |           . |  |
    |<---Dmin/2-->|  |
    |                |
    |                |
    |<-----D/2------>|
    */

    vec pt1,pt2,pt3,pt4,pt5;      

    pt1.x = Dmin_2;
    pt1.y = 0;
    pt1.z = 0;
    pt1.w = 1;

    pt2.x = D_2;
    pt2.y = 0;
    pt2.z = Pdiff;
    pt2.w = 1;

    pt3.x = D_2;
    pt3.y = 0;
    pt3.z = Pdiff+Ptip;
    pt3.w = 1;

    pt4.x = Dmin_2;
    pt4.y = 0;
    pt4.z = 2*Pdiff+Ptip;
    pt4.w = 1;

    pt5.x = Dmin_2; // not used, instead pt1 one full cycle later is used
    pt5.y = 0;      // to avoid floating point errors
    pt5.z = P;
    pt5.w = 1;

    int total_segments = (screwHeight/P-1)*segments;

    vec origin = {0};
    vec top = {0};
    top.z = screwHeight;

    vec up = {0};
    up.z = 1;

    vec down = {0};
    down.z = -1;

    float anginc = (float)360/segments;
    vec sliced8Int;
    int needsExtraTris = 0;

    for(int i = -segments; i < total_segments+segments; i++) {
        vec p1,p2,p3,p4,p5;
        vec p1n,p2n,p3n,p4n,p5n;

        vec ob1,ob1n;
        vec ot1,ot1n;

        float ango = (float)360*((i+segments)%segments)/segments;
        float angno = (float)360*((i+segments)%segments+1)/segments;

        float cosao = cos(ango*M_PI/180);
        float sinao = sin(ango*M_PI/180);

        float cosano = cos(angno*M_PI/180);
        float sinano = sin(angno*M_PI/180);

        ob1.x = fD*cosao;
        ob1.y = fD*sinao;
        ob1.z = 0;

        ob1n.x = fD*cosano;
        ob1n.y = fD*sinano;
        ob1n.z = 0;

        ot1.x = fD*cosao;
        ot1.y = fD*sinao;
        ot1.z = screwHeight;

        ot1n.x = fD*cosano;
        ot1n.y = fD*sinano;
        ot1n.z = screwHeight;

        float ang = (float)360*i/segments;
        float angn = (float)360*(i+1)/segments;
        float angc = (float)360*(i+segments)/segments;
        float angnc = (float)360*(i+1+segments)/segments;

        float cosa = cos(ang*M_PI/180);
        float sina = sin(ang*M_PI/180);

        float cosan = cos(angn*M_PI/180);
        float sinan = sin(angn*M_PI/180);

        float cosanc = cos(angnc*M_PI/180);
        float sinanc = sin(angnc*M_PI/180);

        float cosac = cos(angc*M_PI/180);
        float sinac = sin(angc*M_PI/180);

        float z = P*ang/360;
        float zn = P*angn/360;
        float zc = P*angc/360;
        float znc = P*angnc/360;

        mat t;
        mat tn;
        mat tc;
        mat tnc;

        t.xx = cosa;
        t.xy = sina;
        t.xz = 0;
        t.xw = 0;

        t.yx = -sina;
        t.yy = cosa;
        t.yz = 0;
        t.yw = 0;

        t.zx = 0;
        t.zy = 0;
        t.zz = 1;
        t.zw = 0;

        t.tx = 0;
        t.ty = 0;
        t.tz = z;
        t.tw = 1;

        tn.xx = cosan;
        tn.xy = sinan;
        tn.xz = 0;
        tn.xw = 0;

        tn.yx = -sinan;
        tn.yy = cosan;
        tn.yz = 0;
        tn.yw = 0;

        tn.zx = 0;
        tn.zy = 0;
        tn.zz = 1;
        tn.zw = 0;

        tn.tx = 0;
        tn.ty = 0;
        tn.tz = zn;
        tn.tw = 1;

        tnc.xx = cosanc;
        tnc.xy = sinanc;
        tnc.xz = 0;
        tnc.xw = 0;

        tnc.yx = -sinanc;
        tnc.yy = cosanc;
        tnc.yz = 0;
        tnc.yw = 0;

        tnc.zx = 0;
        tnc.zy = 0;
        tnc.zz = 1;
        tnc.zw = 0;

        tnc.tx = 0;
        tnc.ty = 0;
        tnc.tz = znc;
        tnc.tw = 1;

        tc.xx = cosac;
        tc.xy = sinac;
        tc.xz = 0;
        tc.xw = 0;

        tc.yx = -sinac;
        tc.yy = cosac;
        tc.yz = 0;
        tc.yw = 0;

        tc.zx = 0;
        tc.zy = 0;
        tc.zz = 1;
        tc.zw = 0;

        tc.tx = 0;
        tc.ty = 0;
        tc.tz = zc;
        tc.tw = 1;

        vec_mat_mult(&pt1, &t, &p1);
        vec_mat_mult(&pt2, &t, &p2);
        vec_mat_mult(&pt3, &t, &p3);
        vec_mat_mult(&pt4, &t, &p4);
        vec_mat_mult(&pt1, &tc, &p5); // using pt1 with a transform of 1 
                                      // full cycle around to avoid 
                                      // floating point roundoff errors

        vec_mat_mult(&pt1, &tn, &p1n);
        vec_mat_mult(&pt2, &tn, &p2n);
        vec_mat_mult(&pt3, &tn, &p3n);
        vec_mat_mult(&pt4, &tn, &p4n);
        vec_mat_mult(&pt1, &tnc, &p5n); // using pt1 with a transform of 1
                                        // full cycle around to avoid 
                                        // floating point roundoff errors

        if(i < 0) {
            int wrote_outer_tri = 0;

            vec int1,int2;
            int tris_written;
            if(write_sliced_tri(outf, &p1,&p1n,&p2n,female,&origin,&up,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int2,&origin,&int1,0);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ob1,0);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ob1n,&ob1,0);
                        write_tri(outf,&int2,&int1,&ob1,0);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p1,&p2n,&p2,female,&origin,&up,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int2,&origin,&int1,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ob1,0);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ob1n,&ob1,0);
                        write_tri(outf,&int2,&int1,&ob1,0);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p2,&p2n,&p3n,female,&origin,&up,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int2,&origin,&int1,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ob1,0);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ob1n,&ob1,0);
                        write_tri(outf,&int2,&int1,&ob1,0);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;


            if(write_sliced_tri(outf, &p2,&p3n,&p3,female,&origin,&up,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int2,&origin,&int1,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ob1,0);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ob1n,&ob1,0);
                        write_tri(outf,&int2,&int1,&ob1,0);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p3,&p3n,&p4n,female,&origin,&up,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int2,&origin,&int1,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ob1,0);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ob1n,&ob1,0);
                        write_tri(outf,&int2,&int1,&ob1,0);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p3,&p4n,&p4,female,&origin,&up,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int2,&origin,&int1,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ob1,0);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ob1n,&ob1,0);
                        write_tri(outf,&int2,&int1,&ob1,0);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p4,&p4n,&p5n,female,&origin,&up,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int2,&origin,&int1,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ob1,0);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ob1n,&ob1,0);
                        write_tri(outf,&int2,&int1,&ob1,0);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p4,&p5n,&p5,female,&origin,&up,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int2,&origin,&int1,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ob1,0);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ob1n,&ob1,0);
                        write_tri(outf,&int2,&int1,&ob1,0);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

        } else if(i >= total_segments) {
            int wrote_outer_tri = 0;
            vec int1,int2;
            int tris_written;
            if(write_sliced_tri(outf, &p1,&p1n,&p2n,female,&top,&down,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int1,&top,&int2,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ot1,1);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ot1n,&ot1,1);
                        write_tri(outf,&int2,&int1,&ot1,1);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }

                if(i == total_segments+segments-1 && needsExtraTris) {
                    write_tri(outf, &int1,&p1n,&sliced8Int,female);
                    num_tris += 1;

                    if(male) {
                        write_tri(outf, &int1,&sliced8Int,&top,female);
                        num_tris += 1;
                    } else {
                        write_tri(outf, &int1,&sliced8Int,&ot1n,female);
                        num_tris += 1;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p1,&p2n,&p2,female,&top,&down,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int1,&top,&int2,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ot1,1);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ot1n,&ot1,1);
                        write_tri(outf,&int2,&int1,&ot1,1);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p2,&p2n,&p3n,female,&top,&down,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int1,&top,&int2,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ot1,1);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ot1n,&ot1,1);
                        write_tri(outf,&int2,&int1,&ot1,1);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;


            if(write_sliced_tri(outf, &p2,&p3n,&p3,female,&top,&down,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int1,&top,&int2,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ot1,1);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ot1n,&ot1,1);
                        write_tri(outf,&int2,&int1,&ot1,1);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p3,&p3n,&p4n,female,&top,&down,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int1,&top,&int2,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ot1,1);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ot1n,&ot1,1);
                        write_tri(outf,&int2,&int1,&ot1,1);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p3,&p4n,&p4,female,&top,&down,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int1,&top,&int2,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ot1,1);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ot1n,&ot1,1);
                        write_tri(outf,&int2,&int1,&ot1,1);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p4,&p4n,&p5n,female,&top,&down,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int1,&top,&int2,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ot1,1);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ot1n,&ot1,1);
                        write_tri(outf,&int2,&int1,&ot1,1);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
            }
            num_tris += tris_written;

            if(write_sliced_tri(outf, &p4,&p5n,&p5,female,&top,&down,&int1,&int2,&tris_written)) {
                if(male) {
                    write_tri(outf,&int1,&top,&int2,female);
                    num_tris += 1;
                } else {
                    if(wrote_outer_tri) {
                        write_tri(outf,&int2,&int1,&ot1,1);
                        num_tris += 1;
                    } else {
                        write_tri(outf,&int1,&ot1n,&ot1,1);
                        write_tri(outf,&int2,&int1,&ot1,1);
                        wrote_outer_tri = 1;
                        num_tris += 2;
                    }
                }
                if(i == total_segments && !vec_equals(&int2,&p5)) {
                    needsExtraTris = 1;
                    vec_copy(&int2,&sliced8Int);
                }
            }
            num_tris += tris_written;
        } else {
            write_quad(outf, &p1,&p1n,&p2n,&p2,female);
            write_quad(outf, &p2,&p2n,&p3n,&p3,female);
            write_quad(outf, &p3,&p3n,&p4n,&p4,female);
            write_quad(outf, &p4,&p4n,&p5n,&p5,female);
            num_tris += 8;
        }
    }

    if(female) {
        for(int i = 0; i < segments; i++) {
            vec ob1,ob1n;
            vec ot1,ot1n;

            float ang = (float)360*i/segments;
            float angn = (float)360*(i+1)/segments;

            float cosa = cos(ang*M_PI/180);
            float sina = sin(ang*M_PI/180);

            float cosan = cos(angn*M_PI/180);
            float sinan = sin(angn*M_PI/180);

            ob1.x = fD*cosa;
            ob1.y = fD*sina;
            ob1.z = 0;

            ob1n.x = fD*cosan;
            ob1n.y = fD*sinan;
            ob1n.z = 0;

            ot1.x = fD*cosa;
            ot1.y = fD*sina;
            ot1.z = screwHeight;

            ot1n.x = fD*cosan;
            ot1n.y = fD*sinan;
            ot1n.z = screwHeight;

            write_quad(outf,&ob1,&ob1n,&ot1n,&ot1,0);
            num_tris += 2;
        }
    }

    fseek(outf, 80, SEEK_SET);
    fwrite(&num_tris, 4, 1, outf);

    fclose(outf);

    return 0;
}
Beispiel #3
0
void write_poly(FILE *f, vec *poly, int num_pts, int rev) {
    for(int i = 1; i < num_pts-1; i++) {
        write_tri(f, &poly[0], &poly[i], &poly[i+1], rev);
    }
}
Beispiel #4
0
// returns true if triangle intersects plane, int1 and int2 will be set
// to the intersection points
// returns false if all points are above or below the plane
int write_sliced_tri(FILE *f,
                      vec *p1,
                      vec *p2,
                      vec *p3,
                      int rev,
                      vec *p,  // point that lies in the slicing plane  
                      vec *n,   // normal of slicing plane, keep points in the direction of normal
                      vec *int1, // output, intersecting pt1, returned only if intersection occurs
                      vec *int2, // output, intersecting pt2, returned only if intersection occurs
                      int *tris) // output, number of tris written
                      {
    vec trin;
    tri_normal(p1,p2,p3,rev,&trin);

    point_state_t state1;
    point_state_t state2;
    point_state_t state3;

    state1 = point_state(p1,p,n);
    state2 = point_state(p2,p,n);
    state3 = point_state(p3,p,n);

    if((state1 == ABOVE || state1 == ON) && 
       (state2 == ABOVE || state2 == ON) && 
       (state3 == ABOVE || state3 == ON)) {
        // all points are above or on plane, write tri normally
        write_tri(f,p1,p2,p3,rev);
        *tris = 1;
        return 0;
    } else if((state1 == BELOW || state1 == ON) &&
              (state2 == BELOW || state2 == ON) && 
              (state3 == BELOW || state3 == ON)) {
        // all points are below or on plane, cull entire tri
        *tris = 0;
        return 0;
    } else {
        // triangle intersects plane

        if(state1 == ON) {
            vec tmp1,tmp2;
            float r;

            vec_copy(p1, int1);

            vec_sub(p2,p3,&tmp1);
            vec_sub(p,p3,&tmp2);
            r = vec_dot(n,&tmp2)/vec_dot(n,&tmp1);

            int2->x = p3->x + r*tmp1.x;
            int2->y = p3->y + r*tmp1.y;
            int2->z = p3->z + r*tmp1.z;

            if(state2 == ABOVE) {
                write_tri(f,p1,p2,int2,rev);
            } else {
                write_tri(f,p1,int2,p3,rev);
            }
            *tris = 1;
            return 1;
        }

        if(state2 == ON) {
            vec tmp1,tmp2;
            float r;

            vec_copy(p2, int1);

            vec_sub(p1,p3,&tmp1);
            vec_sub(p,p3,&tmp2);
            r = vec_dot(n,&tmp2)/vec_dot(n,&tmp1);

            int2->x = p3->x + r*tmp1.x;
            int2->y = p3->y + r*tmp1.y;
            int2->z = p3->z + r*tmp1.z;

            if(state1 == ABOVE) {
                write_tri(f,p1,p2,int2,rev);
            } else {
                write_tri(f,p2,p3,int2,rev);
            }
            *tris = 1;
            return 1;
        }

        if(state3 == ON) {
            vec tmp1,tmp2;
            float r;

            vec_copy(p3, int2);

            vec_sub(p1,p2,&tmp1);
            vec_sub(p,p2,&tmp2);
            r = vec_dot(n,&tmp2)/vec_dot(n,&tmp1);

            int1->x = p2->x + r*tmp1.x;
            int1->y = p2->y + r*tmp1.y;
            int1->z = p2->z + r*tmp1.z;

            if(state1 == ABOVE) {
                write_tri(f,p1,int1,p3,rev);
            } else {
                write_tri(f,int1,p2,p3,rev);
            }
            *tris = 1;
            return 1;
        }

        if((state1 == ABOVE && state2 == ABOVE) ||
            (state1 == BELOW && state2 == BELOW)) {
            vec tmp1,tmp2,tmp3;
            float r1,r2;

            vec_sub(p2,p3,&tmp1);
            vec_sub(p1,p3,&tmp2);
            vec_sub(p,p3,&tmp3);

            r1 = vec_dot(n,&tmp3)/vec_dot(n,&tmp1);
            r2 = vec_dot(n,&tmp3)/vec_dot(n,&tmp2);

            int1->x = p3->x + r1*tmp1.x;
            int1->y = p3->y + r1*tmp1.y;
            int1->z = p3->z + r1*tmp1.z;

            int2->x = p3->x + r2*tmp2.x;
            int2->y = p3->y + r2*tmp2.y;
            int2->z = p3->z + r2*tmp2.z;

            if(state3 == ABOVE) {
                write_tri(f,int1,p3,int2,rev);
                *tris = 1;
            } else {
                write_quad(f,p1,p2,int1,int2,rev);
                *tris = 2;
            }
            return 1;
        }

        if((state2 == ABOVE && state3 == ABOVE) ||
            (state2 == BELOW && state3 == BELOW)) {
            vec tmp1,tmp2,tmp3;
            float r1,r2;

            vec_sub(p2,p1,&tmp1);
            vec_sub(p3,p1,&tmp2);
            vec_sub(p,p1,&tmp3);

            r1 = vec_dot(n,&tmp3)/vec_dot(n,&tmp1);
            r2 = vec_dot(n,&tmp3)/vec_dot(n,&tmp2);

            int1->x = p1->x + r1*tmp1.x;
            int1->y = p1->y + r1*tmp1.y;
            int1->z = p1->z + r1*tmp1.z;

            int2->x = p1->x + r2*tmp2.x;
            int2->y = p1->y + r2*tmp2.y;
            int2->z = p1->z + r2*tmp2.z;

            if(state1 == ABOVE) {
                write_tri(f,p1,int1,int2,rev);
                *tris = 1;
            } else {
                write_quad(f,int1,p2,p3,int2,rev);
                *tris = 2;
            }
            return 1;
        }

        if((state1 == ABOVE && state3 == ABOVE) || 
            (state1 == BELOW && state3 == BELOW)) {
            vec tmp1,tmp2,tmp3;
            float r1,r2;

            vec_sub(p1,p2,&tmp1);
            vec_sub(p3,p2,&tmp2);
            vec_sub(p,p2,&tmp3);

            r1 = vec_dot(n,&tmp3)/vec_dot(n,&tmp1);
            r2 = vec_dot(n,&tmp3)/vec_dot(n,&tmp2);

            int1->x = p2->x + r1*tmp1.x;
            int1->y = p2->y + r1*tmp1.y;
            int1->z = p2->z + r1*tmp1.z;

            int2->x = p2->x + r2*tmp2.x;
            int2->y = p2->y + r2*tmp2.y;
            int2->z = p2->z + r2*tmp2.z;

            if(state2 == ABOVE) {
                write_tri(f,int1,p2,int2,rev);
                *tris = 1;
            } else {
                write_quad(f,p1,int1,int2,p3,rev);
                *tris = 2;
            }
            return 1;
        }
    }


    *tris = 0;
    return 0;
}