File indexing completed on 2025-08-03 08:19:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <iostream>
0028 #include <fstream>
0029 #include <math.h>
0030 #include <stdlib.h>
0031
0032 using namespace std;
0033
0034
0035
0036
0037
0038
0039
0040 class GeneralElement
0041 {
0042 protected:
0043 static const int DIM = 4;
0044 double *centroid;
0045 double *normal;
0046 int normal_calculated;
0047 int centroid_calculated;
0048 virtual void calculate_centroid() {};
0049 virtual void calculate_normal() {};
0050 void check_normal_direction(double *normal, double *out);
0051 public:
0052 GeneralElement();
0053 ~GeneralElement();
0054 double *get_centroid();
0055 double *get_normal();
0056 };
0057
0058
0059
0060
0061
0062
0063 GeneralElement::GeneralElement()
0064 {
0065 normal_calculated = 0;
0066 centroid_calculated = 0;
0067 centroid = new double[DIM];
0068 normal = new double[DIM];
0069 }
0070
0071
0072
0073
0074
0075
0076 GeneralElement::~GeneralElement()
0077 {
0078 delete[] centroid;
0079 delete[] normal;
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 void GeneralElement::check_normal_direction(double *normal, double *out)
0092 {
0093
0094
0095 double dot_product = 0;
0096 for (int i=0; i < DIM; i++) {
0097 dot_product += out[i]*normal[i];
0098 }
0099
0100
0101 if ( dot_product < 0 ) {
0102 for (int i=0; i < DIM; i++) {
0103 normal[i] = -normal[i];
0104 }
0105 }
0106 }
0107
0108
0109
0110
0111
0112
0113
0114
0115 double *GeneralElement::get_centroid()
0116 {
0117 if ( !centroid_calculated )
0118 calculate_centroid();
0119 return centroid;
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129 double *GeneralElement::get_normal()
0130 {
0131 if ( !normal_calculated )
0132 calculate_normal();
0133 return normal;
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143 class Line : public GeneralElement
0144 {
0145 private:
0146 static const int LINE_CORNERS = 2;
0147 static const int LINE_DIM = 2;
0148 int x1,x2;
0149 int start_point;
0150 int end_point;
0151 double **corners;
0152 double *out;
0153 int *const_i;
0154 void calculate_centroid();
0155 void calculate_normal();
0156 public:
0157 Line();
0158 ~Line();
0159 void init(double**,double*,int*);
0160 void flip_start_end();
0161 double *get_start();
0162 double *get_end();
0163 double *get_out();
0164 };
0165
0166
0167
0168
0169
0170
0171
0172 Line::Line()
0173 {
0174 GeneralElement();
0175 corners = new double*[LINE_CORNERS];
0176 for (int i=0; i < LINE_CORNERS; i++) {
0177 corners[i] = new double[DIM];
0178 }
0179 out = new double[DIM];
0180 const_i = new int[DIM-LINE_DIM];
0181 }
0182
0183
0184
0185
0186
0187
0188 Line::~Line()
0189 {
0190 for (int i=0; i < LINE_CORNERS; i++) {
0191 delete[] corners[i];
0192 }
0193 delete[] corners;
0194 delete[] out;
0195 delete[] const_i;
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 void Line::init(double **p, double *o, int *c)
0209 {
0210
0211 for (int i=0; i < LINE_CORNERS; i++) {
0212 for (int j=0; j < DIM; j++) {
0213 corners[i][j] = p[i][j];
0214 if ( i==0 ) {
0215 out[j] = o[j];
0216 }
0217 }
0218 }
0219
0220
0221 start_point = 0;
0222 end_point = 1;
0223
0224 for (int i=0; i < DIM-LINE_DIM; i++) {
0225 const_i[i] = c[i];
0226 }
0227
0228
0229 if ( c[0] == 0 ) {
0230 if ( c[1] == 1 ) {
0231 x1 = 2; x2 = 3;
0232 } else if ( c[1] == 2 ) {
0233 x1 = 1; x2 = 3;
0234 } else {
0235 x1 = 1; x2 = 2;
0236 }
0237 } else if ( c[0] == 1 ) {
0238 if ( c[1] == 2 ) {
0239 x1 = 0; x2 = 3;
0240 } else {
0241 x1 = 0; x2 = 2;
0242 }
0243 } else {
0244 x1 = 0; x2 = 1;
0245 }
0246
0247
0248
0249 normal_calculated = 0;
0250 centroid_calculated = 0;
0251 }
0252
0253
0254
0255
0256
0257
0258
0259 void Line::calculate_centroid()
0260 {
0261
0262 for (int i=0; i < DIM; i++) {
0263 centroid[i] = (corners[0][i] + corners[1][i])/2.0;
0264 }
0265 centroid_calculated = 1;
0266 }
0267
0268
0269
0270
0271
0272
0273 void Line::calculate_normal()
0274 {
0275
0276 if ( !centroid_calculated )
0277 calculate_centroid();
0278
0279 normal[x1] = -(corners[1][x2] - corners[0][x2]);
0280 normal[x2] = corners[1][x1] - corners[0][x1];
0281 normal[const_i[0]] = 0;
0282 normal[const_i[1]] = 0;
0283
0284 double *Vout = new double[DIM];
0285 for (int j=0; j < DIM; j++) {
0286 Vout[j] = out[j] - centroid[j];
0287 }
0288 check_normal_direction(normal,Vout);
0289 delete[] Vout;
0290 normal_calculated = 1;
0291 }
0292
0293
0294
0295
0296
0297
0298 void Line::flip_start_end()
0299 {
0300 int temp = start_point;
0301 start_point = end_point;
0302 end_point = temp;
0303 }
0304
0305
0306
0307
0308
0309
0310
0311
0312 double *Line::get_start()
0313 {
0314 return corners[start_point];
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324 double *Line::get_end()
0325 {
0326 return corners[end_point];
0327 }
0328
0329
0330
0331
0332
0333
0334
0335
0336 double *Line::get_out()
0337 {
0338 return out;
0339 }
0340
0341
0342
0343
0344
0345
0346
0347 class Polygon : public GeneralElement
0348 {
0349 private:
0350 static const int MAX_LINES = 24;
0351 static const int POLYGON_DIM = 3;
0352 Line **lines;
0353 int Nlines;
0354 int x1,x2,x3;
0355 int const_i;
0356 void calculate_centroid();
0357 void calculate_normal();
0358 public:
0359 Polygon();
0360 ~Polygon();
0361 void init(int);
0362 bool add_line(Line*,int);
0363 int get_Nlines();
0364 Line** get_lines();
0365 void print(ofstream &file,double*);
0366 };
0367
0368
0369
0370
0371
0372
0373
0374 Polygon::Polygon()
0375 {
0376 GeneralElement();
0377 lines = new Line*[MAX_LINES];
0378 }
0379
0380
0381
0382
0383
0384
0385 Polygon::~Polygon()
0386 {
0387 delete[] lines;
0388 }
0389
0390
0391
0392
0393
0394
0395
0396
0397 void Polygon::init(int c)
0398 {
0399
0400 const_i = c;
0401
0402 x1 = -1;
0403 x2 = -1;
0404 x3 = -1;
0405 for (int i=0; i < DIM; i++) {
0406 if ( i != c ) {
0407 if ( x1 < 0 ) {
0408 x1 = i;
0409 } else if ( x2 < 0 ) {
0410 x2 = i;
0411 } else {
0412 x3 = i;
0413 }
0414 }
0415 }
0416
0417
0418
0419 Nlines = 0;
0420 normal_calculated = 0;
0421 centroid_calculated = 0;
0422 }
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436 bool Polygon::add_line(Line *l, int donotcheck)
0437 {
0438 double eps = 1e-10;
0439
0440
0441 if ( donotcheck || Nlines == 0 ) {
0442 lines[Nlines] = l;
0443 Nlines++;
0444 return true;
0445 } else {
0446
0447
0448 double *p1 = l->get_start();
0449 double *p2 = l->get_end();
0450 double *p3 = lines[Nlines-1]->get_end();
0451 double diff1 = 0;
0452 double diff2 = 0;
0453 for (int j=0; j < DIM; j++) {
0454 diff1 += fabs(p1[j]-p3[j]);
0455 diff2 += fabs(p2[j]-p3[j]);
0456 }
0457
0458
0459 if ( diff1 < eps || diff2 < eps ) {
0460
0461
0462 if ( diff2 < eps )
0463 l->flip_start_end();
0464 lines[Nlines] = l;
0465 Nlines++;
0466 return true;
0467 }
0468
0469 return false;
0470 }
0471 }
0472
0473
0474
0475
0476
0477
0478 void Polygon::calculate_centroid()
0479 {
0480
0481 double *mean = new double[DIM];
0482 for (int i=0; i < DIM; i++ ) {
0483 mean[i] = 0;
0484 }
0485
0486
0487 for (int i=0; i < Nlines; i++ ) {
0488 double *p1 = lines[i]->get_start();
0489 double *p2 = lines[i]->get_end();
0490 for (int j=0; j < DIM; j++ ) {
0491 mean[j] += p1[j] + p2[j];
0492 }
0493 }
0494 for (int j=0; j < DIM; j++ ) {
0495 mean[j] = mean[j]/double(2.0*Nlines);
0496 }
0497
0498
0499 if ( Nlines == 3 ) {
0500 for (int i=0; i < DIM; i++) {
0501 centroid[i] = mean[i];
0502 }
0503 centroid_calculated = 1;
0504 delete[] mean;
0505 return;
0506 }
0507
0508
0509
0510 double *sum_up = new double[DIM];
0511 double sum_down = 0;
0512 for (int i=0; i < DIM; i++) {
0513 sum_up[i] = 0;
0514 }
0515
0516 double *a = new double[DIM];
0517 double *b = new double[DIM];
0518
0519 double *cm_i = new double[DIM];
0520 for (int i=0; i < Nlines; i++) {
0521 double *p1 = lines[i]->get_start();
0522 double *p2 = lines[i]->get_end();
0523 for (int j=0; j < DIM; j++) {
0524 cm_i[j] = (p1[j] + p2[j] + mean[j])/3.0;
0525 }
0526
0527 for (int j=0; j < DIM; j++) {
0528 a[j] = p1[j] - mean[j];
0529 b[j] = p2[j] - mean[j];
0530 }
0531
0532 double A_i = 0.5*sqrt( pow(a[x2]*b[x3]-a[x3]*b[x2],2.0) + pow(a[x1]*b[x3]-a[x3]*b[x1],2.0) + pow(a[x2]*b[x1]-a[x1]*b[x2],2.0) );
0533
0534 for (int j=0; j < DIM; j++) {
0535 sum_up[j] += cm_i[j]*A_i;
0536 }
0537 sum_down += A_i;
0538 }
0539
0540
0541 for (int i=0; i < DIM; i++) {
0542 centroid[i] = sum_up[i]/sum_down;
0543 }
0544
0545 centroid_calculated = 1;
0546 delete[] sum_up;
0547 delete[] mean;
0548 delete[] a;
0549 delete[] b;
0550 delete[] cm_i;
0551 }
0552
0553
0554
0555
0556
0557
0558
0559 void Polygon::calculate_normal()
0560 {
0561
0562 if ( !centroid_calculated )
0563 calculate_centroid();
0564
0565
0566 double **normals = new double*[Nlines];
0567 double *Vout = new double[DIM];
0568 for (int i=0; i < Nlines; i++) {
0569 normals[i] = new double[DIM];
0570 for (int j=0; j < DIM; j++) {
0571 normals[i][j] = 0;
0572 }
0573 }
0574
0575 double *a = new double[DIM];
0576 double *b = new double[DIM];
0577
0578 for (int i=0; i < Nlines; i++) {
0579
0580 double *p1 = lines[i]->get_start();
0581 double *p2 = lines[i]->get_end();
0582 for (int j=0; j < DIM; j++) {
0583 a[j] = p1[j] - centroid[j];
0584 b[j] = p2[j] - centroid[j];
0585 }
0586
0587 normals[i][x1] = 0.5*(a[x2]*b[x3]-a[x3]*b[x2]);
0588 normals[i][x2] = -0.5*(a[x1]*b[x3]-a[x3]*b[x1]);
0589 normals[i][x3] = 0.5*(a[x1]*b[x2]-a[x2]*b[x1]);
0590 normals[i][const_i] = 0;
0591
0592 double *o = lines[i]->get_out();
0593 for (int j=0; j < DIM; j++) {
0594 Vout[j] = o[j] - centroid[j];
0595 }
0596
0597 check_normal_direction(normals[i],Vout);
0598 }
0599
0600 for (int i=0; i < DIM; i++) {
0601 normal[i] = 0;
0602 }
0603 for (int i=0; i < Nlines; i++) {
0604 for (int j=0; j < DIM; j++) {
0605 normal[j] += normals[i][j];
0606 }
0607 }
0608
0609 normal_calculated = 1;
0610 delete[] a;
0611 delete[] b;
0612 for (int i=0; i < Nlines; i++) {
0613 delete[] normals[i];
0614 }
0615 delete[] normals;
0616 delete[] Vout;
0617 }
0618
0619
0620
0621
0622
0623
0624
0625
0626 int Polygon::get_Nlines()
0627 {
0628 return Nlines;
0629 }
0630
0631
0632
0633
0634
0635
0636
0637
0638 Line** Polygon::get_lines()
0639 {
0640 return lines;
0641 }
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652 void Polygon::print(ofstream &file, double *pos)
0653 {
0654 for (int i=0; i < Nlines; i++) {
0655 double *p1 = lines[i]->get_start();
0656 double *p2 = lines[i]->get_end();
0657 file << pos[x1] + p1[x1] << " " << pos[x2] + p1[x2] << " " << pos[x3] + p1[x3];
0658 file << " " << pos[x1] + p2[x1] << " " << pos[x2] + p2[x2] << " " << pos[x3] + p2[x3];
0659 file << " " << pos[x1] + centroid[x1] << " " << pos[x2] + centroid[x2] << " " << pos[x3] + centroid[x3] << endl;
0660 }
0661 }
0662
0663
0664
0665
0666
0667
0668
0669 class Polyhedron : public GeneralElement
0670 {
0671 private:
0672 static const int MAX_POLYGONS = 24;
0673 Polygon **polygons;
0674 int Npolygons;
0675 int Ntetrahedra;
0676 int x1,x2,x3,x4;
0677 bool lines_equal(Line*,Line*);
0678 void tetravolume(double*,double*,double*,double*);
0679 void calculate_centroid();
0680 void calculate_normal();
0681 public:
0682 Polyhedron();
0683 ~Polyhedron();
0684 void init();
0685 bool add_polygon(Polygon*,int);
0686 };
0687
0688
0689
0690
0691
0692
0693
0694 Polyhedron::Polyhedron()
0695 {
0696 GeneralElement();
0697 polygons = new Polygon*[MAX_POLYGONS];
0698 }
0699
0700
0701
0702
0703
0704
0705 Polyhedron::~Polyhedron()
0706 {
0707 delete[] polygons;
0708 }
0709
0710
0711
0712
0713
0714
0715 void Polyhedron::init()
0716 {
0717
0718 x1 = 0;
0719 x2 = 1;
0720 x3 = 2;
0721 x4 = 3;
0722
0723
0724
0725 Npolygons = 0;
0726 Ntetrahedra = 0;
0727 normal_calculated = 0;
0728 centroid_calculated = 0;
0729 }
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743 bool Polyhedron::add_polygon(Polygon *p, int donocheck)
0744 {
0745
0746
0747 if ( donocheck || Npolygons == 0 ) {
0748 polygons[Npolygons] = p;
0749 Npolygons++;
0750 Ntetrahedra += p->get_Nlines();
0751 return true;
0752 } else {
0753
0754
0755 for (int i=0; i < Npolygons; i++) {
0756 int Nlines1 = p->get_Nlines();
0757 int Nlines2 = polygons[i]->get_Nlines();
0758 Line **lines1 = p->get_lines();
0759 Line **lines2 = polygons[i]->get_lines();
0760 for (int j=0; j < Nlines1; j++) {
0761 for (int k=0; k < Nlines2; k++) {
0762 if ( lines_equal(lines1[j],lines2[k]) ) {
0763 polygons[Npolygons] = p;
0764 Npolygons++;
0765 Ntetrahedra += p->get_Nlines();
0766 return true;
0767 }
0768 }
0769 }
0770 }
0771
0772 return false;
0773 }
0774 }
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786 bool Polyhedron::lines_equal(Line *l1, Line *l2)
0787 {
0788 double eps = 1e-10;
0789 double *p11 = l1->get_start();
0790 double *p12 = l1->get_end();
0791 double *p21 = l2->get_start();
0792 double diff1 = 0;
0793 double diff2 = 0;
0794 for (int i=0; i < DIM; i++) {
0795 diff1 += fabs(p11[i]-p21[i]);
0796 diff2 += fabs(p12[i]-p21[i]);
0797 if ( diff1 > eps && diff2 > eps )
0798 return false;
0799 }
0800
0801 return true;
0802 }
0803
0804
0805
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815 void Polyhedron::tetravolume(double *a, double *b, double *c, double *n)
0816 {
0817 double bc01 = b[0]*c[1]-b[1]*c[0];
0818 double bc02 = b[0]*c[2]-b[2]*c[0];
0819 double bc03 = b[0]*c[3]-b[3]*c[0];
0820 double bc12 = b[1]*c[2]-b[2]*c[1];
0821 double bc13 = b[1]*c[3]-b[3]*c[1];
0822 double bc23 = b[2]*c[3]-b[3]*c[2];
0823 n[0] = 1.0/6.0*(a[1]*bc23 - a[2]*bc13 + a[3]*bc12);
0824 n[1] = -1.0/6.0*(a[0]*bc23 - a[2]*bc03 + a[3]*bc02);
0825 n[2] = 1.0/6.0*(a[0]*bc13 - a[1]*bc03 + a[3]*bc01);
0826 n[3] = -1.0/6.0*(a[0]*bc12 - a[1]*bc02 + a[2]*bc01);
0827
0828
0829
0830
0831
0832
0833
0834
0835 }
0836
0837
0838
0839
0840
0841
0842 void Polyhedron::calculate_centroid()
0843 {
0844 double *mean = new double[DIM];
0845 for (int i=0; i < DIM; i++ ) {
0846 mean[i] = 0;
0847 }
0848
0849 for (int i=0; i < Npolygons; i++ ) {
0850 int Nlines = polygons[i]->get_Nlines();
0851 Line **lines = polygons[i]->get_lines();
0852 for (int j=0; j < Nlines; j++ ) {
0853 double *p1 = lines[j]->get_start();
0854 double *p2 = lines[j]->get_end();
0855 for (int k=0; k < DIM; k++ ) {
0856 mean[k] += p1[k] + p2[k];
0857 }
0858 }
0859 }
0860 for (int j=0; j < DIM; j++ ) {
0861 mean[j] = mean[j]/double(2.0*Ntetrahedra);
0862 }
0863
0864 double *a = new double[DIM];
0865 double *b = new double[DIM];
0866 double *c = new double[DIM];
0867 double *n = new double[DIM];
0868 double *cm_i = new double[DIM];
0869 double *sum_up = new double[DIM];
0870 double sum_down = 0;
0871 for (int i=0; i < DIM; i++) {
0872 sum_up[i] = 0;
0873 }
0874 for (int i=0; i < Npolygons; i++ ) {
0875 int Nlines = polygons[i]->get_Nlines();
0876 Line **lines = polygons[i]->get_lines();
0877 double *cent = polygons[i]->get_centroid();
0878 for (int j=0; j < Nlines; j++) {
0879 double *p1 = lines[j]->get_start();
0880 double *p2 = lines[j]->get_end();
0881
0882 for (int k=0; k < DIM; k++) {
0883 cm_i[k] = (p1[k] + p2[k] + cent[k] + mean[k])/4.0;
0884 }
0885
0886
0887 for (int k=0; k < DIM; k++) {
0888 a[k] = p1[k] - mean[k];
0889 b[k] = p2[k] - mean[k];
0890 c[k] = cent[k] - mean[k];
0891 }
0892
0893 tetravolume(a,b,c,n);
0894 double V_i = 0;
0895 for (int k=0; k < DIM; k++) {
0896 V_i += n[k]*n[k];
0897 }
0898 V_i = sqrt(V_i);
0899
0900 for (int k=0; k < DIM; k++) {
0901 sum_up[k] += cm_i[k]*V_i;
0902 }
0903 sum_down += V_i;
0904 }
0905 }
0906
0907
0908 for (int i=0; i < DIM; i++) {
0909 centroid[i] = sum_up[i]/sum_down;
0910 }
0911
0912 centroid_calculated = 1;
0913 delete[] a;
0914 delete[] b;
0915 delete[] c;
0916 delete[] n;
0917 delete[] cm_i;
0918 delete[] sum_up;
0919 delete[] mean;
0920 }
0921
0922
0923
0924
0925
0926
0927
0928 void Polyhedron::calculate_normal()
0929 {
0930
0931
0932 if ( !centroid_calculated )
0933 calculate_centroid();
0934
0935 double *Vout = new double[DIM];
0936 double *a = new double[DIM];
0937 double *b = new double[DIM];
0938 double *c = new double[DIM];
0939 double **normals = new double*[Ntetrahedra];
0940 for (int i=0; i < Ntetrahedra; i++) {
0941 normals[i] = new double[DIM];
0942 }
0943 int Ntetra = 0;
0944 for (int i=0; i < Npolygons; i++ ) {
0945 int Nlines = polygons[i]->get_Nlines();
0946 Line **lines = polygons[i]->get_lines();
0947 double *cent = polygons[i]->get_centroid();
0948 for (int j=0; j < Nlines; j++) {
0949 double *p1 = lines[j]->get_start();
0950 double *p2 = lines[j]->get_end();
0951
0952 for (int k=0; k < DIM; k++) {
0953 a[k] = p1[k] - centroid[k];
0954 b[k] = p2[k] - centroid[k];
0955 c[k] = cent[k] - centroid[k];
0956 }
0957
0958 tetravolume(a,b,c,normals[Ntetra]);
0959
0960 double *o = lines[j]->get_out();
0961 for (int k=0; k < DIM; k++) {
0962 Vout[k] = o[k] - centroid[k];
0963 }
0964 check_normal_direction(normals[Ntetra],Vout);
0965 Ntetra++;
0966 }
0967 }
0968
0969 for (int i=0; i < DIM; i++) {
0970 normal[i] = 0;
0971 }
0972 for (int i=0; i < Ntetrahedra; i++) {
0973 for (int j=0; j < DIM; j++) {
0974 normal[j] += normals[i][j];
0975 }
0976 }
0977
0978 normal_calculated = 1;
0979 for (int i=0; i < Ntetrahedra; i++) {
0980 delete[] normals[i];
0981 }
0982 delete[] a;
0983 delete[] b;
0984 delete[] c;
0985 delete[] normals;
0986 delete[] Vout;
0987 }
0988
0989
0990
0991
0992
0993
0994
0995
0996 class Square
0997 {
0998 private:
0999 static const int DIM = 4;
1000 static const int SQUARE_DIM = 2;
1001 static const int MAX_POINTS = 4;
1002 static const int MAX_LINES = 2;
1003 double **points;
1004 double **cuts;
1005 double **out;
1006 double **points_temp;
1007 double *out_temp;
1008 int *const_i;
1009 double *const_value;
1010 int x1, x2;
1011 double *dx;
1012 int Ncuts;
1013 int Nlines;
1014 Line *lines;
1015 int ambiguous;
1016 void ends_of_edge(double);
1017 void find_outside(double);
1018 public:
1019 Square();
1020 ~Square();
1021 void init(double**,int*,double*,double*);
1022 void construct_lines(double);
1023 int is_ambiguous();
1024 int get_Nlines();
1025 Line* get_lines();
1026 };
1027
1028
1029
1030
1031
1032
1033
1034 Square::Square()
1035 {
1036 cuts = new double*[MAX_POINTS];
1037 out = new double*[MAX_POINTS];
1038 points = new double*[SQUARE_DIM];
1039 const_i = new int[DIM-SQUARE_DIM];
1040 const_value = new double[DIM-SQUARE_DIM];
1041 lines = new Line[MAX_LINES];
1042 for (int i=0; i < SQUARE_DIM; i++) {
1043 points[i] = new double[SQUARE_DIM];
1044 }
1045 for (int i=0; i < MAX_POINTS; i++) {
1046 cuts[i] = new double[SQUARE_DIM];
1047 out[i] = new double[SQUARE_DIM];
1048 }
1049 int Npoints = 2;
1050 points_temp = new double*[SQUARE_DIM];
1051 out_temp = new double[DIM];
1052 for (int j=0; j < Npoints; j++) {
1053 points_temp[j] = new double[DIM];
1054 }
1055 ambiguous = 0;
1056 }
1057
1058
1059
1060
1061
1062
1063 Square::~Square()
1064 {
1065 for (int i=0; i < DIM-SQUARE_DIM; i++) {
1066 delete[] points[i];
1067 }
1068 delete[] points;
1069 for (int i=0; i < MAX_POINTS; i++) {
1070 delete[] cuts[i];
1071 delete[] out[i];
1072 }
1073 delete[] cuts;
1074 delete[] out;
1075 delete[] const_i;
1076 delete[] const_value;
1077 delete[] lines;
1078 for (int i=0; i < SQUARE_DIM; i++) {
1079 delete[] points_temp[i];
1080 }
1081 delete[] points_temp;
1082 delete[] out_temp;
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097 void Square::init(double **sq, int *c_i, double *c_v, double *dex)
1098 {
1099 for (int i=0; i < SQUARE_DIM; i++) {
1100 for (int j=0; j < SQUARE_DIM; j++) {
1101 points[i][j] = sq[i][j];
1102 }
1103 }
1104 for (int i=0; i < DIM-SQUARE_DIM; i++) {
1105 const_i[i] = c_i[i];
1106 const_value[i] = c_v[i];
1107 }
1108 dx = dex;
1109 x1 = -1;
1110 x2 = -1;
1111 for (int i=0; i < DIM; i++) {
1112 if ( i != const_i[0] && i != const_i[1] ) {
1113 if ( x1 < 0 ) {
1114 x1 = i;
1115 } else {
1116 x2 = i;
1117 }
1118 }
1119 }
1120
1121
1122 Ncuts = 0;
1123 Nlines = 0;
1124 ambiguous = 0;
1125 }
1126
1127
1128
1129
1130
1131
1132
1133
1134 void Square::construct_lines(double E0)
1135 {
1136
1137 int above=0;
1138 for (int i=0; i < DIM-SQUARE_DIM; i++) {
1139 for (int j=0; j < DIM-SQUARE_DIM; j++) {
1140 if ( points[i][j] >= E0 )
1141 above++;
1142 }
1143 }
1144
1145
1146 if ( above == 0 || above == 4 ) {
1147 Nlines = 0;
1148 return;
1149 }
1150
1151
1152
1153 ends_of_edge(E0);
1154 if ( Ncuts > 0 )
1155 find_outside(E0);
1156
1157 for (int i=0; i < Ncuts; i++) {
1158 points_temp[i%2][x1] = cuts[i][0];
1159 points_temp[i%2][x2] = cuts[i][1];
1160 points_temp[i%2][const_i[0]] = const_value[0];
1161 points_temp[i%2][const_i[1]] = const_value[1];
1162
1163
1164 if ( i%2 == 1 ) {
1165 out_temp[x1] = out[i/2][0];
1166 out_temp[x2] = out[i/2][1];
1167 out_temp[const_i[0]] = const_value[0];
1168 out_temp[const_i[1]] = const_value[1];
1169 lines[i/2].init(points_temp,out_temp,const_i);
1170 Nlines++;
1171 }
1172 }
1173 }
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192 void Square::ends_of_edge(double E0)
1193 {
1194
1195 if ( (points[0][0]-E0)*(points[1][0]-E0) < 0 ) {
1196 cuts[Ncuts][0] = (points[0][0]-E0)/(points[0][0]-points[1][0])*dx[x1];
1197 cuts[Ncuts][1] = 0;
1198 Ncuts++;
1199 } else if ( points[0][0] == E0 && points[1][0] < E0 ) {
1200 cuts[Ncuts][0] = 1e-9*dx[x1];
1201 cuts[Ncuts][1] = 0;
1202 Ncuts++;
1203 } else if ( points[1][0] == E0 && points[0][0] < E0 ) {
1204 cuts[Ncuts][0] = (1.0-1e-9)*dx[x1];
1205 cuts[Ncuts][1] = 0;
1206 Ncuts++;
1207 }
1208
1209 if ( (points[0][0]-E0)*(points[0][1]-E0) < 0 ) {
1210 cuts[Ncuts][0] = 0;
1211 cuts[Ncuts][1] = (points[0][0]-E0)/(points[0][0]-points[0][1])*dx[x2];
1212 Ncuts++;
1213 } else if ( points[0][0] == E0 && points[0][1] < E0 ) {
1214 cuts[Ncuts][0] = 0;
1215 cuts[Ncuts][1] = 1e-9*dx[x2];
1216 Ncuts++;
1217 } else if ( points[0][1] == E0 && points[0][0] < E0 ) {
1218 cuts[Ncuts][0] = 0;
1219 cuts[Ncuts][1] = (1.0-1e-9)*dx[x2];
1220 Ncuts++;
1221 }
1222
1223 if ( (points[1][0]-E0)*(points[1][1]-E0) < 0 ) {
1224 cuts[Ncuts][0] = dx[x1];
1225 cuts[Ncuts][1] = (points[1][0]-E0)/(points[1][0]-points[1][1])*dx[x2];
1226 Ncuts++;
1227 } else if ( points[1][0] == E0 && points[1][1] < E0 ) {
1228 cuts[Ncuts][0] = dx[x1];
1229 cuts[Ncuts][1] = 1e-9*dx[x2];
1230 Ncuts++;
1231 } else if ( points[1][1] == E0 && points[1][0] < E0 ) {
1232 cuts[Ncuts][0] = dx[x1];
1233 cuts[Ncuts][1] = (1.0-1e-9)*dx[x2];
1234 Ncuts++;
1235 }
1236
1237 if ( (points[0][1]-E0)*(points[1][1]-E0) < 0 ) {
1238 cuts[Ncuts][0] = (points[0][1]-E0)/(points[0][1]-points[1][1])*dx[x1];
1239 cuts[Ncuts][1] = dx[x2];
1240 Ncuts++;
1241 } else if ( points[0][1] == E0 && points[1][1] < E0 ) {
1242 cuts[Ncuts][0] = 1e-9*dx[x1];
1243 cuts[Ncuts][1] = dx[x2];
1244 Ncuts++;
1245 } else if ( points[1][1] == E0 && points[0][1] < E0 ) {
1246 cuts[Ncuts][0] = (1.0-1e-9)*dx[x1];
1247 cuts[Ncuts][1] = dx[x2];
1248 Ncuts++;
1249 }
1250 if ( Ncuts != 0 && Ncuts != 2 && Ncuts != 4 ) {
1251 cout << "Error in EndsOfEdge: Ncuts " << Ncuts << endl;
1252 exit(1);
1253 }
1254 }
1255
1256
1257
1258
1259
1260
1261
1262
1263 void Square::find_outside(double E0)
1264 {
1265 if ( Ncuts == 4 ) {
1266 ambiguous = 1;
1267
1268 double Emid = 0;
1269 for (int i=0; i < 2; i++) {
1270 for (int j=0; j < 2; j++) {
1271 Emid += 0.25*points[i][j];
1272 }
1273 }
1274
1275
1276
1277 if ( (points[0][0] < E0 && Emid < E0) || (points[0][0] > E0 && Emid > E0) ) {
1278 for (int i=0; i < 2; i++) {
1279 double temp = cuts[1][i];
1280 cuts[1][i] = cuts[2][i];
1281 cuts[2][i] = temp;
1282 }
1283 }
1284
1285
1286 if ( (Emid-E0) < 0 ) {
1287 for (int i=0; i < 2; i++) {
1288 for (int j=0; j < 2; j++) {
1289 if ( j == 0 )
1290 out[i][j] = 0.5*dx[x1];
1291 else
1292 out[i][j] = 0.5*dx[x2];
1293 }
1294 }
1295 } else {
1296
1297 if ( (points[0][0]-E0) < 0 ) {
1298 for (int i=0; i < 2; i++) {
1299 out[0][i] = 0;
1300 if ( i == 0 )
1301 out[1][i] = dx[x1];
1302 else
1303 out[1][i] = dx[x2];
1304 }
1305
1306 } else {
1307 out[0][0] = dx[x1];
1308 out[0][1] = 0;
1309 out[1][0] = 0;
1310 out[1][1] = dx[x2];
1311 }
1312 }
1313 } else {
1314 for (int i=0; i < 2; i++) {
1315 for (int j=0; j < 2; j++) {
1316 out[i][j] = 0;
1317 }
1318 }
1319 int Nout = 0;
1320 for (int i=0; i < 2; i++) {
1321 for (int j=0; j < 2; j++) {
1322 if ( points[i][j] < E0 ) {
1323 out[0][0] += i*dx[x1];
1324 out[0][1] += j*dx[x2];
1325 Nout++;
1326 }
1327 }
1328 }
1329 if ( Nout > 0 ) {
1330 for (int i=0; i < 2; i++) {
1331 for (int j=0; j < 2; j++) {
1332 out[i][j] = out[i][j]/double(Nout);
1333 }
1334 }
1335 }
1336 }
1337 }
1338
1339
1340
1341
1342
1343
1344
1345
1346 int Square::is_ambiguous()
1347 {
1348 return ambiguous;
1349 }
1350
1351
1352
1353
1354
1355
1356
1357
1358 int Square::get_Nlines()
1359 {
1360 return Nlines;
1361 }
1362
1363
1364
1365
1366
1367
1368
1369
1370 Line* Square::get_lines()
1371 {
1372 return lines;
1373 }
1374
1375
1376
1377
1378
1379
1380
1381
1382 class Cube
1383 {
1384 private:
1385 static const int DIM = 4;
1386 static const int CUBE_DIM = 4;
1387 static const int MAX_POLY = 8;
1388 static const int NSQUARES = 6;
1389 static const int STEPS = 2;
1390 double ***cube;
1391 Line **lines;
1392 Polygon *polygons;
1393 Square *squares;
1394 int Nlines;
1395 int Npolygons;
1396 int ambiguous;
1397 int const_i;
1398 double const_value;
1399 int x1,x2,x3;
1400 double *dx;
1401 void split_to_squares();
1402 void check_ambiguous(int);
1403 public:
1404 Cube();
1405 ~Cube();
1406 void init(double***&,int,double,double*&);
1407 void construct_polygons(double);
1408 int get_Nlines();
1409 int get_Npolygons();
1410 int is_ambiguous();
1411 Polygon* get_polygons();
1412 };
1413
1414
1415
1416
1417
1418
1419 Cube::Cube()
1420 {
1421 cube = new double**[STEPS];
1422 for (int i=0; i < STEPS; i++) {
1423 cube[i] = new double*[STEPS];
1424 for (int j=0; j < STEPS; j++) {
1425 cube[i][j] = new double[STEPS];
1426 }
1427 }
1428 lines = new Line*[NSQUARES*2];
1429 polygons = new Polygon[MAX_POLY];
1430 squares = new Square[NSQUARES];
1431 }
1432
1433
1434
1435
1436
1437
1438 Cube::~Cube()
1439 {
1440 for (int i=0; i < STEPS; i++) {
1441 for (int j=0; j < STEPS; j++) {
1442 delete[] cube[i][j];
1443 }
1444 delete[] cube[i];
1445 }
1446 delete[] cube;
1447 delete[] lines;
1448 delete[] polygons;
1449 delete[] squares;
1450 }
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463 void Cube::init(double ***&c, int c_i, double c_v, double *&dex)
1464 {
1465 const_i = c_i;
1466 const_value = c_v;
1467 dx = dex;
1468
1469 x1 = -1;
1470 x2 = -1;
1471 x3 = -1;
1472 for (int i=0; i < DIM; i++) {
1473 if ( i != c_i ) {
1474 if ( x1 < 0 ) {
1475 x1 = i;
1476 } else if ( x2 < 0 ) {
1477 x2 = i;
1478 } else {
1479 x3 = i;
1480 }
1481 }
1482 }
1483 for (int i=0; i < STEPS; i++) {
1484 for (int j=0; j < STEPS; j++) {
1485 for (int k=0; k < STEPS; k++) {
1486 cube[i][j][k] = c[i][j][k];
1487 }
1488 }
1489 }
1490
1491
1492 Nlines = 0;
1493 Npolygons = 0;
1494 ambiguous = 0;
1495 }
1496
1497
1498
1499
1500
1501
1502 void Cube::split_to_squares()
1503 {
1504 double **sq = new double*[STEPS];
1505 int *c_i = new int[STEPS];
1506 double *c_v = new double[STEPS];
1507 for (int i=0; i < STEPS; i++) {
1508 sq[i] = new double[STEPS];
1509 }
1510 int Nsquares = 0;
1511 for (int i=0; i < DIM; i++) {
1512
1513
1514 if ( i != const_i ) {
1515 c_i[0] = const_i;
1516 c_i[1] = i;
1517 for (int j=0; j < STEPS; j++) {
1518 c_v[0] = const_value;
1519 c_v[1] = j*dx[i];
1520 for (int ci1=0; ci1 < STEPS; ci1++) {
1521 for (int ci2=0; ci2 < STEPS; ci2++) {
1522 if ( i == x1 ) {
1523 sq[ci1][ci2] = cube[j][ci1][ci2];
1524 } else if ( i == x2 ) {
1525 sq[ci1][ci2] = cube[ci1][j][ci2];
1526 } else {
1527 sq[ci1][ci2] = cube[ci1][ci2][j];
1528 }
1529 }
1530 }
1531 squares[Nsquares].init(sq,c_i,c_v,dx);
1532 Nsquares++;
1533 }
1534 }
1535 }
1536 for (int i=0; i < STEPS; i++) {
1537 delete[] sq[i];
1538 }
1539 delete[] sq;
1540 delete[] c_i;
1541 delete[] c_v;
1542 }
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552 void Cube::construct_polygons(double value0)
1553 {
1554
1555
1556 split_to_squares();
1557 for (int i=0; i < NSQUARES; i++) {
1558 squares[i].construct_lines(value0);
1559 }
1560
1561 Nlines = 0;
1562 for (int i=0; i < NSQUARES; i++) {
1563 int Nline = squares[i].get_Nlines();
1564 Line *l = squares[i].get_lines();
1565 for (int j=0; j < Nline; j++) {
1566 lines[Nlines] = &l[j];
1567 double *p = lines[Nlines]->get_start();
1568 p = lines[Nlines]->get_end();
1569 Nlines++;
1570 }
1571 l = NULL;
1572 }
1573
1574 if ( Nlines == 0 ) {
1575 return;
1576 }
1577
1578 check_ambiguous(Nlines);
1579 if ( ambiguous > 0 ) {
1580
1581
1582 int *not_used = new int[Nlines];
1583 for (int i=0; i < Nlines; i++) {
1584 not_used[i] = 1;
1585 }
1586 int used = 0;
1587
1588 do {
1589 if ( Nlines - used < 3 ) {
1590 cout << "Error: cannot construct polygon from " << Nlines -used << " lines" << endl;
1591 exit(1);
1592 }
1593
1594 polygons[Npolygons].init(const_i);
1595
1596 for (int i=0; i < Nlines; i++) {
1597 if ( not_used[i] ) {
1598
1599 if ( polygons[Npolygons].add_line(lines[i],0) ) {
1600 not_used[i]=0;
1601 used++;
1602
1603
1604 i=0;
1605 }
1606 }
1607 }
1608
1609 Npolygons++;
1610 } while ( used < Nlines );
1611 delete[] not_used;
1612 } else {
1613
1614
1615 polygons[Npolygons].init(const_i);
1616 for (int i=0; i < Nlines; i++) {
1617 polygons[Npolygons].add_line(lines[i],1);
1618 }
1619 Npolygons++;
1620 }
1621 }
1622
1623
1624
1625
1626
1627
1628 void Cube::check_ambiguous(int Nlines)
1629 {
1630
1631 for (int i=0; i < NSQUARES; i++) {
1632 if ( squares[i].is_ambiguous() ) {
1633 ambiguous++;
1634 }
1635 }
1636
1637
1638
1639 if ( ambiguous == 0 && Nlines == 6 ) {
1640 ambiguous++;
1641 }
1642 }
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652 int Cube::is_ambiguous()
1653 {
1654 return ambiguous;
1655 }
1656
1657
1658
1659
1660
1661
1662
1663
1664 int Cube::get_Nlines()
1665 {
1666 return Nlines;
1667 }
1668
1669
1670
1671
1672
1673
1674
1675
1676 int Cube::get_Npolygons()
1677 {
1678 return Npolygons;
1679 }
1680
1681
1682
1683
1684
1685
1686
1687
1688 Polygon* Cube::get_polygons()
1689 {
1690 return polygons;
1691 }
1692
1693
1694
1695
1696
1697
1698
1699 class Hypercube
1700 {
1701 private:
1702 static const int DIM = 4;
1703 static const int MAX_POLY = 10;
1704 static const int NCUBES = 8;
1705 static const int STEPS = 2;
1706 double ****hcube;
1707 Polyhedron *polyhedrons;
1708 Polygon **polygons;
1709 Cube *cubes;
1710 int Npolyhedrons;
1711 int ambiguous;
1712 int x1,x2,x3,x4;
1713 double *dx;
1714 void split_to_cubes();
1715 void check_ambiguous(double);
1716 public:
1717 Hypercube();
1718 ~Hypercube();
1719 void init(double****,double*);
1720 void construct_polyhedrons(double);
1721 int get_Npolyhedrons();
1722 Polyhedron* get_polyhedrons();
1723 };
1724
1725
1726
1727
1728
1729
1730 Hypercube::Hypercube()
1731 {
1732 hcube = new double***[STEPS];
1733 for (int i=0; i < STEPS; i++) {
1734 hcube[i] = new double**[STEPS];
1735 for (int j=0; j < STEPS; j++) {
1736 hcube[i][j] = new double*[STEPS];
1737 for (int k=0; k < STEPS; k++) {
1738 hcube[i][j][k] = new double[STEPS];
1739 }
1740 }
1741 }
1742 polyhedrons = new Polyhedron[MAX_POLY];
1743 polygons = new Polygon*[NCUBES*10];
1744 cubes = new Cube[NCUBES];
1745 }
1746
1747
1748
1749
1750
1751
1752 Hypercube::~Hypercube()
1753 {
1754 for (int i=0; i < STEPS; i++) {
1755 for (int j=0; j < STEPS; j++) {
1756 for (int k=0; k < STEPS; k++) {
1757 delete[] hcube[i][j][k];
1758 }
1759 delete[] hcube[i][j];
1760 }
1761 delete[] hcube[i];
1762 }
1763 delete[] hcube;
1764 delete[] polyhedrons;
1765 delete[] polygons;
1766 delete[] cubes;
1767 }
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778 void Hypercube::init(double ****c, double *dex)
1779 {
1780 dx = dex;
1781
1782 x1 = 0;
1783 x2 = 1;
1784 x3 = 2;
1785 x4 = 3;
1786 for (int i=0; i < STEPS; i++) {
1787 for (int j=0; j < STEPS; j++) {
1788 for (int k=0; k < STEPS; k++) {
1789 for (int l=0; l < STEPS; l++) {
1790 hcube[i][j][k][l] = c[i][j][k][l];
1791 }
1792 }
1793 }
1794 }
1795
1796
1797 Npolyhedrons = 0;
1798 ambiguous = 0;
1799 }
1800
1801
1802
1803
1804
1805
1806 void Hypercube::split_to_cubes()
1807 {
1808 double ***cu = new double**[STEPS];
1809 for (int i=0; i < STEPS; i++) {
1810 cu[i] = new double*[STEPS];
1811 for (int j=0; j < STEPS; j++) {
1812 cu[i][j] = new double[STEPS];
1813 }
1814 }
1815 int Ncubes = 0;
1816 for (int i=0; i < DIM; i++) {
1817
1818
1819 int c_i = i;
1820 for (int j=0; j < STEPS; j++) {
1821 double c_v = j*dx[i];
1822 for (int ci1=0; ci1 < STEPS; ci1++) {
1823 for (int ci2=0; ci2 < STEPS; ci2++) {
1824 for (int ci3=0; ci3 < STEPS; ci3++) {
1825 if ( i == x1 ) {
1826 cu[ci1][ci2][ci3] = hcube[j][ci1][ci2][ci3];
1827 } else if ( i == x2 ) {
1828 cu[ci1][ci2][ci3] = hcube[ci1][j][ci2][ci3];
1829 } else if ( i == x3 ) {
1830 cu[ci1][ci2][ci3] = hcube[ci1][ci2][j][ci3];
1831 } else {
1832 cu[ci1][ci2][ci3] = hcube[ci1][ci2][ci3][j];
1833 }
1834 }
1835 }
1836 }
1837 cubes[Ncubes].init(cu,c_i,c_v,dx);
1838 Ncubes++;
1839 }
1840 }
1841 for (int i=0; i < STEPS; i++) {
1842 for (int j=0; j < STEPS; j++) {
1843 delete[] cu[i][j];
1844 }
1845 delete[] cu[i];
1846 }
1847 delete[] cu;
1848 }
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858 void Hypercube::construct_polyhedrons(double value0)
1859 {
1860 split_to_cubes();
1861 for (int i=0; i < NCUBES; i++) {
1862 cubes[i].construct_polygons(value0);
1863 }
1864 int Npolygons = 0;
1865
1866 for (int i=0; i < NCUBES; i++) {
1867 int Npoly = cubes[i].get_Npolygons();
1868 Polygon *p = cubes[i].get_polygons();
1869 for (int j=0; j < Npoly; j++) {
1870 polygons[Npolygons] = &p[j];
1871 Npolygons++;
1872 }
1873 }
1874 check_ambiguous(value0);
1875 if ( ambiguous > 0 ) {
1876
1877
1878 int *not_used = new int[Npolygons];
1879 for (int i=0; i < Npolygons; i++) {
1880 not_used[i] = 1;
1881 }
1882 int used = 0;
1883
1884 do {
1885
1886 polyhedrons[Npolyhedrons].init();
1887
1888 for (int i=0; i < Npolygons; i++) {
1889 if ( not_used[i] ) {
1890
1891 if ( polyhedrons[Npolyhedrons].add_polygon(polygons[i],0) ) {
1892 not_used[i]=0;
1893 used++;
1894
1895
1896 i=0;
1897 }
1898 }
1899 }
1900
1901 Npolyhedrons++;
1902 } while ( used < Npolygons );
1903 delete[] not_used;
1904
1905
1906
1907 } else {
1908
1909
1910 polyhedrons[Npolyhedrons].init();
1911 for (int i=0; i < Npolygons; i++) {
1912 polyhedrons[Npolyhedrons].add_polygon(polygons[i],1);
1913 }
1914
1915 Npolyhedrons++;
1916 }
1917 }
1918
1919
1920
1921
1922
1923
1924 void Hypercube::check_ambiguous(double value0)
1925 {
1926 for (int i=0; i < NCUBES; i++) {
1927 if ( cubes[i].is_ambiguous() ) {
1928 ambiguous++;
1929 }
1930 }
1931 if ( ambiguous == 0 ) {
1932 int Nlines = 0;
1933 for (int i=0; i < NCUBES; i++) {
1934 Nlines += cubes[i].get_Nlines();
1935 }
1936 int points = 0;
1937 for (int i1=0; i1 < STEPS; i1++) {
1938 for (int i2=0; i2 < STEPS; i2++) {
1939 for (int i3=0; i3 < STEPS; i3++) {
1940 for (int i4=0; i4 < STEPS; i4++) {
1941 if ( hcube[i1][i2][i3][i4] < value0 ) {
1942 points++;
1943 }
1944 }
1945 }
1946 }
1947 }
1948 if ( points > 8 ) {
1949 points = 16-points;
1950 }
1951
1952
1953
1954
1955
1956
1957
1958
1959 if ( Nlines == 24 && points == 2 ) {
1960 ambiguous++;
1961 }
1962 }
1963 }
1964
1965
1966
1967
1968
1969
1970
1971
1972 int Hypercube::get_Npolyhedrons()
1973 {
1974 return Npolyhedrons;
1975 }
1976
1977
1978
1979
1980
1981
1982
1983
1984 Polyhedron* Hypercube::get_polyhedrons()
1985 {
1986 return polyhedrons;
1987 }
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999 class Cornelius
2000 {
2001 private:
2002 static const int STEPS = 2;
2003 static const int DIM = 4;
2004 static const int MAX_ELEMENTS = 10;
2005 int Nelements;
2006 double **normals;
2007 double **centroids;
2008 int cube_dim;
2009 int initialized;
2010 int print_initialized;
2011 double value0;
2012 double *dx;
2013 ofstream output_print;
2014 void surface_3d(double***,double*,int);
2015 Square cu2d;
2016 Cube cu3d;
2017 Hypercube cu4d;
2018 public:
2019 Cornelius();
2020 ~Cornelius();
2021 void init(int,double,double*);
2022 void init_print(string);
2023 void find_surface_2d(double**);
2024 void find_surface_3d(double***);
2025 void find_surface_3d_print(double***,double*);
2026 void find_surface_4d(double****);
2027 int get_Nelements();
2028 double **get_normals();
2029 double **get_centroids();
2030 double **get_normals_4d();
2031 double **get_centroids_4d();
2032 double get_centroid_elem(int,int);
2033 double get_normal_elem(int,int);
2034 };
2035
2036
2037
2038
2039
2040
2041 Cornelius::Cornelius()
2042 {
2043 Nelements = 0;
2044 initialized = 0;
2045 print_initialized = 0;
2046 normals = new double*[MAX_ELEMENTS];
2047 centroids = new double*[MAX_ELEMENTS];
2048 for (int i=0; i < MAX_ELEMENTS; i++) {
2049 normals[i] = new double[DIM];
2050 centroids[i] = new double[DIM];
2051 }
2052 }
2053
2054
2055
2056
2057
2058
2059 Cornelius::~Cornelius()
2060 {
2061 for (int i=0; i < MAX_ELEMENTS; i++) {
2062 delete[] normals[i];
2063 delete[] centroids[i];
2064 }
2065 delete[] normals;
2066 delete[] centroids;
2067 if ( initialized ) {
2068 delete[] dx;
2069 }
2070
2071 if ( print_initialized ) {
2072 output_print.close();
2073 }
2074 }
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087 void Cornelius::init(int d, double v0, double *dex)
2088 {
2089 cube_dim = d;
2090 value0 = v0;
2091 if ( initialized != 1 ) {
2092 dx = new double[DIM];
2093 }
2094 for (int i=0; i < DIM; i++) {
2095 if ( i < DIM-cube_dim ) {
2096 dx[i] = 1;
2097 } else {
2098 dx[i] = dex[i-(DIM-cube_dim)];
2099 }
2100 }
2101 initialized = 1;
2102 }
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113 void Cornelius::init_print(string filename)
2114 {
2115 output_print.open(filename.c_str());
2116 print_initialized = 1;
2117 }
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127 void Cornelius::find_surface_2d(double **cube)
2128 {
2129 if ( !initialized || cube_dim != 2 ) {
2130 cout << "Cornelius not initialized for 2D case" << endl;
2131 exit(1);
2132 }
2133 int *c_i = new int[cube_dim];
2134 double *c_v = new double[cube_dim];
2135 c_i[0] = 0;
2136 c_i[1] = 1;
2137 c_v[0] = 0;
2138 c_v[1] = 0;
2139 cu2d.init(cube,c_i,c_v,dx);
2140 cu2d.construct_lines(value0);
2141 Nelements = cu2d.get_Nlines();
2142 Line *l = cu2d.get_lines();
2143 for (int i=0; i < Nelements; i++) {
2144 for (int j=0; j < DIM; j++) {
2145 normals[i][j] = l[i].get_normal()[j];
2146 centroids[i][j] = l[i].get_centroid()[j];
2147 }
2148 }
2149 delete[] c_i;
2150 delete[] c_v;
2151 }
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161 void Cornelius::find_surface_3d(double ***cube)
2162 {
2163 double *pos = NULL;
2164 surface_3d(cube,pos,0);
2165 }
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177 void Cornelius::find_surface_3d_print(double ***cube, double *pos)
2178 {
2179 surface_3d(cube,pos,1);
2180 }
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192 void Cornelius::surface_3d(double ***cube, double *pos, int do_print)
2193 {
2194 if ( !initialized || cube_dim != 3 ) {
2195 cout << "Cornelius not initialized for 3D case" << endl;
2196 exit(1);
2197 }
2198
2199
2200
2201 int above = 0;
2202 for (int i=0; i < STEPS; i++) {
2203 for (int j=0; j < STEPS; j++) {
2204 for (int k=0; k < STEPS; k++) {
2205 if ( cube[i][j][k] >= value0 )
2206 above++;
2207 }
2208 }
2209 }
2210 if ( above == 0 || above == 8 ) {
2211
2212 Nelements = 0;
2213 return;
2214 }
2215
2216
2217 int c_i = 0;
2218 double c_v = 0;
2219 cu3d.init(cube,c_i,c_v,dx);
2220
2221 cu3d.construct_polygons(value0);
2222
2223 Nelements = cu3d.get_Npolygons();
2224 Polygon *p = cu3d.get_polygons();
2225 for (int i=0; i < Nelements; i++) {
2226
2227 for (int j=0; j < DIM; j++) {
2228 normals[i][j] = p[i].get_normal()[j];
2229 centroids[i][j] = p[i].get_centroid()[j];
2230 }
2231
2232
2233 if ( print_initialized && do_print ) {
2234 p[i].print(output_print,pos);
2235 }
2236 }
2237 }
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248 void Cornelius::find_surface_4d(double ****cube)
2249 {
2250 if ( !initialized || cube_dim != 4 ) {
2251 cout << "Cornelius not initialized for 4D case" << endl;
2252 exit(1);
2253 }
2254
2255
2256
2257 int above = 0;
2258 for (int i=0; i < STEPS; i++) {
2259 for (int j=0; j < STEPS; j++) {
2260 for (int k=0; k < STEPS; k++) {
2261 for (int l=0; l < STEPS; l++) {
2262 if ( cube[i][j][k][l] >= value0 )
2263 above++;
2264 }
2265 }
2266 }
2267 }
2268 if ( above == 0 || above == 16 ) {
2269
2270 Nelements = 0;
2271 return;
2272 }
2273
2274
2275 cu4d.init(cube,dx);
2276
2277 cu4d.construct_polyhedrons(value0);
2278
2279 Nelements = cu4d.get_Npolyhedrons();
2280 Polyhedron *p = cu4d.get_polyhedrons();
2281 for (int i=0; i < Nelements; i++) {
2282 for (int j=0; j < DIM; j++) {
2283 centroids[i][j] = p[i].get_centroid()[j];
2284 normals[i][j] = p[i].get_normal()[j];
2285 }
2286 }
2287 }
2288
2289
2290
2291
2292
2293
2294
2295
2296 int Cornelius::get_Nelements()
2297 {
2298 return Nelements;
2299 }
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312 double** Cornelius::get_centroids_4d()
2313 {
2314 double **vect = new double*[Nelements];
2315 for (int i=0; i < Nelements; i++) {
2316 vect[i] = new double[DIM];
2317 for (int j=0; j < DIM; j++) {
2318 vect[i][j] = centroids[i][j];
2319 }
2320 }
2321 return vect;
2322 }
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336 double** Cornelius::get_normals_4d()
2337 {
2338 double **vect = new double*[Nelements];
2339 for (int i=0; i < Nelements; i++) {
2340 vect[i] = new double[DIM];
2341 for (int j=0; j < DIM; j++) {
2342 vect[i][j] = normals[i][j];
2343 }
2344 }
2345 return vect;
2346 }
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358 double** Cornelius::get_centroids()
2359 {
2360 double **vect = new double*[Nelements];
2361 for (int i=0; i < Nelements; i++) {
2362 vect[i] = new double[cube_dim];
2363 for (int j=0; j < cube_dim; j++) {
2364 vect[i][j] = centroids[i][j+(DIM-cube_dim)];
2365 }
2366 }
2367 return vect;
2368 }
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381 double** Cornelius::get_normals()
2382 {
2383 double **vect = new double*[Nelements];
2384 for (int i=0; i < Nelements; i++) {
2385 vect[i] = new double[cube_dim];
2386 for (int j=0; j < cube_dim; j++) {
2387 vect[i][j] = normals[i][j+(DIM-cube_dim)];
2388 }
2389 }
2390 return vect;
2391 }
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404 double Cornelius::get_centroid_elem(int i, int j)
2405 {
2406 if ( i >= Nelements || j >= cube_dim ) {
2407 cout << "Cornelius error: asking for an element which does not exist." << endl;
2408 exit(1);
2409 }
2410 return centroids[i][j+(DIM-cube_dim)];
2411 }
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425 double Cornelius::get_normal_elem(int i, int j)
2426 {
2427 if ( i >= Nelements || j >= cube_dim ) {
2428 cout << "Cornelius error: asking for an element which does not exist." << endl;
2429 exit(1);
2430 }
2431 return normals[i][j+(DIM-cube_dim)];
2432 }