| 1 | #include "molecules.hpp"
 | 
|---|
| 2 | #include "boundary.hpp"
 | 
|---|
| 3 | 
 | 
|---|
| 4 | 
 | 
|---|
| 5 | void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, double *Storage, const double RADIUS, molecule mol)
 | 
|---|
| 6 | {
 | 
|---|
| 7 |   /* d2 ist der Normalenvektor auf dem Dreieck,
 | 
|---|
| 8 |    * d1 ist der Vektor, der normal auf der Kante und d2 steht.
 | 
|---|
| 9 |    */
 | 
|---|
| 10 |   Vector dif_a;
 | 
|---|
| 11 |   Vector dif_b;
 | 
|---|
| 12 |   Vector Chord;
 | 
|---|
| 13 |   Vector AngleCheck;
 | 
|---|
| 14 |   atom *Walker;
 | 
|---|
| 15 | 
 | 
|---|
| 16 |   dif_a.CopyVector(&a.x);
 | 
|---|
| 17 |   dif_a.SubtractVector(&Candidate.x);
 | 
|---|
| 18 |   dif_b.CopyVector(&b.x);
 | 
|---|
| 19 |   dif_b.SubtractVector(&Candidate.x);
 | 
|---|
| 20 |   Chord.CopyVector(&a.x);
 | 
|---|
| 21 |   Chord.SubtractVector(&b.x);
 | 
|---|
| 22 |   AngleCheck.CopyVector(&dif_a);
 | 
|---|
| 23 |   AngleCheck.ProjectOntoPlane(&Chord);
 | 
|---|
| 24 | 
 | 
|---|
| 25 |   //Storage eintrag fuer aktuelles Atom
 | 
|---|
| 26 |   if (Chord.Norm()/(2*sin(dif_a.Angle(&dif_b)))<RADIUS) //Using Formula for relation of chord length with inner angle to find of Ball will touch atom
 | 
|---|
| 27 |   {
 | 
|---|
| 28 | 
 | 
|---|
| 29 |     if (dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1))>Storage[1]) //This will give absolute preference to those in "right-hand" quadrants
 | 
|---|
| 30 |       {
 | 
|---|
| 31 |         Storage[0]=(double)Candidate.nr;
 | 
|---|
| 32 |         Storage[1]=1;
 | 
|---|
| 33 |         Storage[2]=AngleCheck.Angle(d2);
 | 
|---|
| 34 |       }
 | 
|---|
| 35 |     else
 | 
|---|
| 36 |       {
 | 
|---|
| 37 |         if ((dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)) == Storage[1] && Storage[1]>0 &&  Storage[2]< AngleCheck.Angle(d2)) or \
 | 
|---|
| 38 |             (dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)) == Storage[1] && Storage[1]<0 &&  Storage[2]> AngleCheck.Angle(d2)))
 | 
|---|
| 39 |           //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first.
 | 
|---|
| 40 |           {
 | 
|---|
| 41 |             Storage[0]=(double)Candidate.nr;
 | 
|---|
| 42 |             Storage[1]=dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1));
 | 
|---|
| 43 |             Storage[2]=AngleCheck.Angle(d2);
 | 
|---|
| 44 |           }
 | 
|---|
| 45 |       }
 | 
|---|
| 46 |   }
 | 
|---|
| 47 | 
 | 
|---|
| 48 |   if (n<5)
 | 
|---|
| 49 |     {
 | 
|---|
| 50 |       for(int i=0; i<mol.NumberOfBondsPerAtom[Candidate.nr];i++)
 | 
|---|
| 51 |         {
 | 
|---|
| 52 |           while (Candidate.nr != (mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr ==Candidate.nr ? mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr : mol.ListOfBondsPerAtom[Candidate.nr][i]->rightatom->nr))
 | 
|---|
| 53 |             {
 | 
|---|
| 54 |               Walker = Walker->next;
 | 
|---|
| 55 |             }
 | 
|---|
| 56 | 
 | 
|---|
| 57 |           Find_next_suitable_point(a, b, *Walker, n+1, d1, d2, Storage, RADIUS, mol);
 | 
|---|
| 58 |         }
 | 
|---|
| 59 |     }
 | 
|---|
| 60 | };
 | 
|---|
| 61 | 
 | 
|---|
| 62 | 
 | 
|---|
| 63 | void Tesselation::Find_next_suitable_triangle(molecule *mol, BoundaryLineSet Line, BoundaryTriangleSet T, const double& RADIUS)
 | 
|---|
| 64 | {
 | 
|---|
| 65 |   Vector CenterOfLine = Line.endpoints[0]->node->x;
 | 
|---|
| 66 |   Vector direction1;
 | 
|---|
| 67 |   Vector direction2;
 | 
|---|
| 68 |   Vector helper;
 | 
|---|
| 69 |   atom* Walker;
 | 
|---|
| 70 | 
 | 
|---|
| 71 |   double Storage[3];
 | 
|---|
| 72 |   Storage[0]=-1.;   // Id must be positive, we see should nothing be done
 | 
|---|
| 73 |   Storage[1]=-1.;   // This direction is either +1 or -1 one, so any result will take precedence over initial values
 | 
|---|
| 74 |   Storage[2]=-10.;  // This is also lower then any value produced by an eligible atom, which are all positive
 | 
|---|
| 75 | 
 | 
|---|
| 76 |   
 | 
|---|
| 77 |   helper.CopyVector(&(Line.endpoints[0]->node->x));
 | 
|---|
| 78 |   for (int i =0; i<3; i++)
 | 
|---|
| 79 |     {
 | 
|---|
| 80 |       if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr && T.endpoints[i]->node->nr!=Line.endpoints[1]->node->nr)
 | 
|---|
| 81 |         {
 | 
|---|
| 82 |           helper.SubtractVector(&T.endpoints[i]->node->x);
 | 
|---|
| 83 |           break;
 | 
|---|
| 84 |         }
 | 
|---|
| 85 |     }
 | 
|---|
| 86 | 
 | 
|---|
| 87 | 
 | 
|---|
| 88 |   direction1.CopyVector(&Line.endpoints[0]->node->x);
 | 
|---|
| 89 |   direction1.SubtractVector(&Line.endpoints[1]->node->x);
 | 
|---|
| 90 |   direction1.VectorProduct(T.NormalVector);
 | 
|---|
| 91 | 
 | 
|---|
| 92 |   if (direction1.ScalarProduct(&helper)>0)
 | 
|---|
| 93 |     {
 | 
|---|
| 94 |       direction1.Scale(-1);
 | 
|---|
| 95 |     }
 | 
|---|
| 96 | 
 | 
|---|
| 97 |   Find_next_suitable_point(*Line.endpoints[0]->node, *Line.endpoints[1]->node, *Line.endpoints[0]->node, 0, &direction1, T.NormalVector, Storage, RADIUS, *mol);
 | 
|---|
| 98 |   
 | 
|---|
| 99 |   // Konstruiere nun neues Dreieck am Ende der Liste der Dreiecke
 | 
|---|
| 100 |   // Next Triangle is Line, atom with number in Storage[0]
 | 
|---|
| 101 | 
 | 
|---|
| 102 |   Walker= mol->start;
 | 
|---|
| 103 |   while (Walker->nr != (int)Storage[0])
 | 
|---|
| 104 |     {
 | 
|---|
| 105 |       Walker = Walker->next;
 | 
|---|
| 106 |     }
 | 
|---|
| 107 | 
 | 
|---|
| 108 |   AddPoint(Walker);
 | 
|---|
| 109 | 
 | 
|---|
| 110 |   BPS[0] = new class BoundaryPointSet(Walker);
 | 
|---|
| 111 |   BPS[1] = new class BoundaryPointSet(Line.endpoints[0]->node);
 | 
|---|
| 112 |   BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount);
 | 
|---|
| 113 |   BPS[0] = new class BoundaryPointSet(Walker);
 | 
|---|
| 114 |   BPS[1] = new class BoundaryPointSet(Line.endpoints[1]->node);
 | 
|---|
| 115 |   BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount);
 | 
|---|
| 116 |   BLS[2] = new class BoundaryLineSet(Line);
 | 
|---|
| 117 | 
 | 
|---|
| 118 |   BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
 | 
|---|
| 119 |   TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) );
 | 
|---|
| 120 |   TrianglesOnBoundaryCount++;
 | 
|---|
| 121 | 
 | 
|---|
| 122 |   for(int i=0;i<NDIM;i++) // sind Linien bereits vorhanden ???
 | 
|---|
| 123 |     {
 | 
|---|
| 124 |       if (LinesOnBoundary.find(BTS->lines[i]) == LinesOnBoundary.end)
 | 
|---|
| 125 |         {
 | 
|---|
| 126 |           LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) );
 | 
|---|
| 127 |           LinesOnBoundaryCount++;
 | 
|---|
| 128 |         }
 | 
|---|
| 129 |     }
 | 
|---|
| 130 |   BTS->GetNormalVector(*BTS->NormalVector);
 | 
|---|
| 131 | 
 | 
|---|
| 132 |   if( (BTS->NormalVector->ScalarProduct(T.NormalVector)<0 && Storage[1]>0) || \
 | 
|---|
| 133 |       (BTS->NormalVector->ScalarProduct(T.NormalVector)>0 && Storage[1]<0))
 | 
|---|
| 134 |     {
 | 
|---|
| 135 |       BTS->NormalVector->Scale(-1);
 | 
|---|
| 136 |     }
 | 
|---|
| 137 |   
 | 
|---|
| 138 | };
 | 
|---|
| 139 | 
 | 
|---|
| 140 | 
 | 
|---|
| 141 | void Find_second_point_for_Tesselation(atom a, atom Candidate, int n, Vector Oben, double* Storage, molecule mol)
 | 
|---|
| 142 | {
 | 
|---|
| 143 |   int i;
 | 
|---|
| 144 |   Vector *AngleCheck;
 | 
|---|
| 145 |   atom* Walker;
 | 
|---|
| 146 | 
 | 
|---|
| 147 |   AngleCheck->CopyVector(&Candidate.x);
 | 
|---|
| 148 |   AngleCheck->SubtractVector(&a.x);
 | 
|---|
| 149 |   if (AngleCheck->ScalarProduct(&Oben) < Storage[1])
 | 
|---|
| 150 |     {
 | 
|---|
| 151 |       Storage[0]=(double)(Candidate.nr);
 | 
|---|
| 152 |       Storage[1]=AngleCheck->ScalarProduct(&Oben);
 | 
|---|
| 153 |     };
 | 
|---|
| 154 | 
 | 
|---|
| 155 |   if (n<5)
 | 
|---|
| 156 |     {
 | 
|---|
| 157 |       for (i = 0; i< mol.NumberOfBondsPerAtom[Candidate.nr]; i++)
 | 
|---|
| 158 |         {
 | 
|---|
| 159 |           Walker = mol.start;
 | 
|---|
| 160 |           while (Candidate.nr != (mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr ==Candidate.nr ? mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr : mol.ListOfBondsPerAtom[Candidate.nr][i]->rightatom->nr))
 | 
|---|
| 161 |             {
 | 
|---|
| 162 |               Walker = Walker->next;
 | 
|---|
| 163 |             };
 | 
|---|
| 164 |           
 | 
|---|
| 165 |           Find_second_point_for_Tesselation(a, *Walker, n+1, Oben, Storage, mol);
 | 
|---|
| 166 |             };
 | 
|---|
| 167 |     };
 | 
|---|
| 168 |   
 | 
|---|
| 169 | 
 | 
|---|
| 170 | };
 | 
|---|
| 171 | 
 | 
|---|
| 172 | 
 | 
|---|
| 173 | void Tesselation::Find_starting_triangle(molecule mol, const double RADIUS)
 | 
|---|
| 174 | {
 | 
|---|
| 175 |   int i=0;
 | 
|---|
| 176 |   atom Walker;
 | 
|---|
| 177 |   atom Walker2;
 | 
|---|
| 178 |   atom Walker3;
 | 
|---|
| 179 |   int max_index[3];
 | 
|---|
| 180 |   double max_coordinate[3];
 | 
|---|
| 181 |   Vector Oben;
 | 
|---|
| 182 |   Vector helper;
 | 
|---|
| 183 | 
 | 
|---|
| 184 |   Oben.Zero();
 | 
|---|
| 185 | 
 | 
|---|
| 186 | 
 | 
|---|
| 187 |   for(i =0; i<3; i++)
 | 
|---|
| 188 |     {
 | 
|---|
| 189 |       max_index[i] =-1;
 | 
|---|
| 190 |       max_coordinate[i] =-1;
 | 
|---|
| 191 |     }
 | 
|---|
| 192 | 
 | 
|---|
| 193 |   Walker = *mol.start;
 | 
|---|
| 194 |   while (Walker.next != NULL)
 | 
|---|
| 195 |     {
 | 
|---|
| 196 |       for (i=0; i<3; i++)
 | 
|---|
| 197 |         {
 | 
|---|
| 198 |           if (Walker.x.x[i]>max_coordinate[i])
 | 
|---|
| 199 |             {
 | 
|---|
| 200 |               max_coordinate[i]=Walker.x.x[i];
 | 
|---|
| 201 |               max_index[i]=Walker.nr;
 | 
|---|
| 202 |             }
 | 
|---|
| 203 |         }
 | 
|---|
| 204 |     }
 | 
|---|
| 205 | 
 | 
|---|
| 206 |   //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0
 | 
|---|
| 207 |   const int k=0;
 | 
|---|
| 208 | 
 | 
|---|
| 209 |   Oben.x[k]=1;
 | 
|---|
| 210 |   Walker = *mol.start;
 | 
|---|
| 211 |   while (Walker.nr != max_index[k])
 | 
|---|
| 212 |     {
 | 
|---|
| 213 |       Walker = *Walker.next;
 | 
|---|
| 214 |     }
 | 
|---|
| 215 | 
 | 
|---|
| 216 |   double Storage[3];
 | 
|---|
| 217 |   Storage[0]=-1.;   // Id must be positive, we see should nothing be done
 | 
|---|
| 218 |   Storage[1]=-2.;   // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
 | 
|---|
| 219 |   Storage[2]=-10.;  // This will be an angle looking for the third point.
 | 
|---|
| 220 | 
 | 
|---|
| 221 | 
 | 
|---|
| 222 |   for (i=0; i< mol.NumberOfBondsPerAtom[Walker.nr]; i++)
 | 
|---|
| 223 |     {
 | 
|---|
| 224 |       Walker2 = *mol.start;
 | 
|---|
| 225 |       while (Walker2.nr != (mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr == Walker.nr ? mol.ListOfBondsPerAtom[Walker.nr][i]->rightatom->nr : mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr) ) 
 | 
|---|
| 226 |         {
 | 
|---|
| 227 |           Walker2 = *Walker2.next;
 | 
|---|
| 228 |         }
 | 
|---|
| 229 | 
 | 
|---|
| 230 |       Find_second_point_for_Tesselation(Walker, Walker2, 0, Oben, Storage, mol);
 | 
|---|
| 231 |     }
 | 
|---|
| 232 | 
 | 
|---|
| 233 |   Walker2 = *mol.start;
 | 
|---|
| 234 | 
 | 
|---|
| 235 |   while (Walker2.nr != int(Storage[0]))
 | 
|---|
| 236 |     {
 | 
|---|
| 237 |       Walker = *Walker.next;
 | 
|---|
| 238 |     }
 | 
|---|
| 239 |   
 | 
|---|
| 240 |   helper.CopyVector(&Walker.x);
 | 
|---|
| 241 |   helper.SubtractVector(&Walker2.x);
 | 
|---|
| 242 |   Oben.ProjectOntoPlane(&helper);
 | 
|---|
| 243 |   helper.VectorProduct(&Oben);
 | 
|---|
| 244 | 
 | 
|---|
| 245 |        Find_next_suitable_point(Walker, Walker2, *(mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr == Walker.nr ? mol.ListOfBondsPerAtom[Walker.nr][i]->rightatom : mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom), 0, &helper, &Oben, Storage, RADIUS, mol);
 | 
|---|
| 246 |   Walker3 = *mol.start;
 | 
|---|
| 247 |   while (Walker3.nr != int(Storage[0]))
 | 
|---|
| 248 |     {
 | 
|---|
| 249 |       Walker3 = *Walker3.next;
 | 
|---|
| 250 |     }
 | 
|---|
| 251 | 
 | 
|---|
| 252 |   //Starting Triangle is Walker, Walker2, index Storage[0]
 | 
|---|
| 253 | 
 | 
|---|
| 254 |   AddPoint(&Walker);
 | 
|---|
| 255 |   AddPoint(&Walker2);
 | 
|---|
| 256 |   AddPoint(&Walker3);
 | 
|---|
| 257 | 
 | 
|---|
| 258 |   BPS[0] = new class BoundaryPointSet(&Walker);
 | 
|---|
| 259 |   BPS[1] = new class BoundaryPointSet(&Walker2);
 | 
|---|
| 260 |   BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount);
 | 
|---|
| 261 |   BPS[0] = new class BoundaryPointSet(&Walker);
 | 
|---|
| 262 |   BPS[1] = new class BoundaryPointSet(&Walker3);
 | 
|---|
| 263 |   BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount);
 | 
|---|
| 264 |   BPS[0] = new class BoundaryPointSet(&Walker);
 | 
|---|
| 265 |   BPS[1] = new class BoundaryPointSet(&Walker2);
 | 
|---|
| 266 |   BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount);  
 | 
|---|
| 267 | 
 | 
|---|
| 268 |   BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
 | 
|---|
| 269 |   TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) );
 | 
|---|
| 270 |   TrianglesOnBoundaryCount++;
 | 
|---|
| 271 | 
 | 
|---|
| 272 |   for(int i=0;i<NDIM;i++) 
 | 
|---|
| 273 |     {
 | 
|---|
| 274 |       LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) );
 | 
|---|
| 275 |       LinesOnBoundaryCount++;
 | 
|---|
| 276 |     };
 | 
|---|
| 277 | 
 | 
|---|
| 278 |        BTS->GetNormalVector(*BTS->NormalVector);
 | 
|---|
| 279 | 
 | 
|---|
| 280 |        if( BTS->NormalVector->ScalarProduct(&Oben)<0)
 | 
|---|
| 281 |          {
 | 
|---|
| 282 |            BTS->NormalVector->Scale(-1);
 | 
|---|
| 283 |          }
 | 
|---|
| 284 | };
 | 
|---|
| 285 | 
 | 
|---|
| 286 | 
 | 
|---|
| 287 | void Find_non_convex_border(Tesselation* Tess, molecule mol) 
 | 
|---|
| 288 | {
 | 
|---|
| 289 |   const double RADIUS =6;
 | 
|---|
| 290 |   Tess->Find_starting_triangle(mol, RADIUS);
 | 
|---|
| 291 | 
 | 
|---|
| 292 |   for (LineMap::iterator baseline = Tess->LinesOnBoundary.begin(); baseline != Tess->LinesOnBoundary.end(); baseline++) 
 | 
|---|
| 293 |     if (baseline->second->TrianglesCount == 1) 
 | 
|---|
| 294 |       {
 | 
|---|
| 295 |         Tess->Find_next_suitable_triangle(&mol, *(baseline->second), baseline->second->triangles.begin()->second, RADIUS); //the line is there, so there is a triangle, but only one.
 | 
|---|
| 296 | 
 | 
|---|
| 297 |       }
 | 
|---|
| 298 |     else
 | 
|---|
| 299 |       {
 | 
|---|
| 300 |         printf("There is a line with %d triangles adjacent", baseline->second->TrianglesCount);
 | 
|---|
| 301 |       }
 | 
|---|
| 302 | };
 | 
|---|