DFNgen  2.0
DFN Model Generator
computationalGeometry.cpp
Go to the documentation of this file.
1 #include <iomanip>
2 #include <algorithm>
4 #include "structures.h"
5 #include <iostream>
6 #include <cmath>
7 #include "vectorFunctions.h"
8 #include "input.h"
9 #include "mathFunctions.h"
10 #include "generatingPoints.h"
11 #include <fstream>
12 #include <random>
13 #include "testing.h"
14 #include "clusterGroups.h"
15 
16 /**********************************************************************/
17 /*********************** 2D rotation matrix ***************************/
24 void applyRotation2D(Poly &newPoly, float angle) {
25 
26  float sinCalc = sin(angle);
27  float cosCalc = cos(angle);
28 
29  // Rotates polygon on x-y plane counter-clockwise
30  for (int i = 0; i < newPoly.numberOfNodes; i++) {
31  int idx = i*3;
32  double x = newPoly.vertices[idx];
33  double y = newPoly.vertices[idx+1];
34  newPoly.vertices[idx] = (x * cosCalc) + (y * sinCalc); // x
35  newPoly.vertices[idx+1] = (x * -sinCalc) + (y * cosCalc); // y
36  newPoly.vertices[idx+2] = 0; // z
37  }
38 }
39 
40 
41 //**********************************************************************/
42 //************************ Translate *********************************/
47 void translate(Poly &newPoly, double *translation) {
48 
49  newPoly.translation[0] = translation[0];
50  newPoly.translation[1] = translation[1];
51  newPoly.translation[2] = translation[2];
52 
53  for (int i = 0; i < newPoly.numberOfNodes; i++) {
54  int idx = i*3;
55  newPoly.vertices[idx] = newPoly.vertices[idx] + translation[0];
56  newPoly.vertices[idx+1] = newPoly.vertices[idx+1] + translation[1];
57  newPoly.vertices[idx+2] = newPoly.vertices[idx+2] + translation[2];
58  }
59 }
60 
61 
62 //*********************************************************************/
63 //******************** Build Rotation Ratrix **************************/
73 double *rotationMatrix(double *normalA, double *normalB) {
74  //***************************************************
75  // Note: Normals must be normalized by this point!!!!!!
76  // Since vectors are normalized, sin = magnitude(AxB) and cos = A dot B
77  //***************************************************
78 
79  // normalA is current normal
80  // nNormalB is target normal
81 
82  // Delete manually with delete[], created with new[]
83  double *xProd = crossProduct(normalA, normalB);
84 
85  // If not parallel
86  if (!(std::abs(xProd[0]) < eps && std::abs(xProd[1]) < eps && std::abs(xProd[2]) < eps)) {
87 
88  // sin = magnitude(AxB) and cos = A . B
89  double sin = sqrt(xProd[0]*xProd[0] + xProd[1]*xProd[1] + xProd[2]*xProd[2]);
90  double cos = dotProduct(normalA, normalB);
91  double v[9] = {0, -xProd[2], xProd[1], xProd[2], 0, -xProd[0], -xProd[1], xProd[0], 0};
92  double scalar = (1.0f-cos)/(sin*sin);
93 
94  double vSquared[9];
95  vSquared[0] = (v[0]*v[0] + v[1]*v[3] + v[2]*v[6])*scalar;
96  vSquared[1] = (v[0]*v[1] + v[1]*v[4] + v[2]*v[7])*scalar;
97  vSquared[2] = (v[0]*v[2] + v[1]*v[5] + v[2]*v[8])*scalar;
98  vSquared[3] = (v[3]*v[0] + v[4]*v[3] + v[5]*v[6])*scalar;
99  vSquared[4] = (v[3]*v[1] + v[4]*v[4] + v[5]*v[7])*scalar;
100  vSquared[5] = (v[3]*v[2] + v[4]*v[5] + v[5]*v[8])*scalar;
101  vSquared[6] = (v[6]*v[0] + v[7]*v[3] + v[8]*v[6])*scalar;
102  vSquared[7] = (v[6]*v[1] + v[7]*v[4] + v[8]*v[7])*scalar;
103  vSquared[8] = (v[6]*v[2] + v[7]*v[5] + v[8]*v[8])*scalar;
104 
105  double *R = new double[9];
106  R[0] = 1 + v[0] + vSquared[0];
107  R[1] = 0 + v[1] + vSquared[1];
108  R[2] = 0 + v[2] + vSquared[2];
109  R[3] = 0 + v[3] + vSquared[3];
110  R[4] = 1 + v[4] + vSquared[4];
111  R[5] = 0 + v[5] + vSquared[5];
112  R[6] = 0 + v[6] + vSquared[6];
113  R[7] = 0 + v[7] + vSquared[7];
114  R[8] = 1 + v[8] + vSquared[8];
115 
116  delete[] xProd;
117  return R; // Make sure to delete R with delete[]
118  }
119  else { // normalA and normalB are parallel, return identity matrix
120  double *R = new double[9];
121  R[0] = 1;
122  R[1] = 0;
123  R[2] = 0;
124  R[3] = 0;
125  R[4] = 1;
126  R[5] = 0;
127  R[6] = 0;
128  R[7] = 0;
129  R[8] = 1;
130 
131  delete[] xProd;
132  return R; // Make sure to delete R with delete[]
133  }
134 }
135 
136 
137 //*********************************************************************/
138 /********** Applies a Rotation Matrix to poly vertices ****************/
139 /**********************************************************************/
140 // RotMatrix = I + V + V^2((1-cos)/sin^2)) rotate to new normal /
141 /**********************************************************************/
147 void applyRotation3D(Poly &newPoly, double *normalB) {
148  // Normals should already be normalized by this point!!!
149 
150  // NormalA: newPoly's current normal
151  // NormalB: target normal
152 
153  // Delete manually with delete[], created with new[]
154  double *xProd = crossProduct(newPoly.normal, normalB);
155 
156  // If not parallel
157  if (!(std::abs(xProd[0]) < eps && std::abs(xProd[1]) < eps && std::abs(xProd[2]) < eps )) {
158 
159  // NOTE: rotationMatrix() requires normals to be normalized
160  double *R = rotationMatrix(newPoly.normal, normalB);
161 
162  // Apply rotation to all vertices
163  for (int i = 0; i < newPoly.numberOfNodes; i++) {
164  int idx = i*3;
165  double vertices[3];
166  vertices[0] = newPoly.vertices[idx] * R[0]
167  + newPoly.vertices[idx+1] * R[1]
168  + newPoly.vertices[idx+2] * R[2];
169  vertices[1] = newPoly.vertices[idx] * R[3]
170  + newPoly.vertices[idx+1] * R[4]
171  + newPoly.vertices[idx+2] * R[5];
172  vertices[2] = newPoly.vertices[idx] * R[6]
173  + newPoly.vertices[idx+1] * R[7]
174  + newPoly.vertices[idx+2] * R[8];
175 
176  newPoly.vertices[idx] = vertices[0];
177  newPoly.vertices[idx+1] = vertices[1];
178  newPoly.vertices[idx+2] = vertices[2];
179  }
180  delete[] R;
181  }
182  // xProd was created dynamically in crossProduct(), need to delete it
183  delete[] xProd;
184 }
185 
186 
187 /**********************************************************************/
188 /* 3D Rotation Matrix for intersection, trip. points, and polygpons **/
189 /**********************************************************************/
190 /* RotMatrix = I + V + V^2((1-cos)/sin^2)) */
191 /**********************************************************************/
207 struct IntPoints polyAndIntersection_RotationToXY(struct IntPoints &intersection, Poly &newPoly, std::vector<Point> &triplePoints, std::vector<Point> &tempTripPts) {
208  // newPoly.normal = newPoly's current normal, should already be normalized
209  // normalB = target normal
210 
211  double normalB[3] = { 0, 0, 1 };
212  IntPoints tempIntpts;
213 
214  // Delete xProd manually, created with new[]
215  double *xProd = crossProduct(newPoly.normal, normalB);
216 
217  // If not parallel (zero vector)
218  if (!(std::abs(xProd[0]) < eps && std::abs(xProd[1]) < eps && std::abs(xProd[2]) < eps )) {
219 
220  // rotationMatrix() requires normals to be normalized
221  double *R = rotationMatrix(newPoly.normal, normalB);
222 
223  // Because the normal's in the polygon structure don't change (we need them to
224  // write params.txt), the xProd check at the top of the function may not work.
225  // Poly vertices may have already been rotated to XY plane but the normal
226  // was unchanged. newPoly.XYPlane resolves this issue. It will tell us if
227  // the polyon has already been rotated to xy plane
228 
229  // Check if nodes are not already on x-y plane:
230  if (newPoly.XYPlane != 1) { // If not on x-y plane:
231  for (int i = 0; i < newPoly.numberOfNodes; i++) {
232  int idx = i*3;
233  double vertices[3];
234  // Apply rotation matrix R to each vertice
235  vertices[0] = newPoly.vertices[idx] * R[0]
236  + newPoly.vertices[idx+1] * R[1]
237  + newPoly.vertices[idx+2] * R[2];
238 
239  vertices[1] = newPoly.vertices[idx] * R[3]
240  + newPoly.vertices[idx+1] * R[4]
241  + newPoly.vertices[idx+2] * R[5];
242 
243  vertices[2] = newPoly.vertices[idx] * R[6]
244  + newPoly.vertices[idx+1] * R[7]
245  + newPoly.vertices[idx+2] * R[8];
246 
247  // Save vertices back to poly struct, now on x-y plane
248  newPoly.vertices[idx] = vertices[0];
249  newPoly.vertices[idx+1] = vertices[1];
250  newPoly.vertices[idx+2] = vertices[2];
251  }
252  }
253 
254  // Rotate intersection endpoints
255  tempIntpts.x1 = intersection.x1 * R[0]
256  + intersection.y1 * R[1]
257  + intersection.z1 * R[2];
258 
259  tempIntpts.y1 = intersection.x1 * R[3]
260  + intersection.y1 * R[4]
261  + intersection.z1 * R[5];
262 
263  tempIntpts.z1 = intersection.x1 * R[6]
264  + intersection.y1 * R[7]
265  + intersection.z1 * R[8];
266 
267  tempIntpts.x2 = intersection.x2 * R[0]
268  + intersection.y2 * R[1]
269  + intersection.z2 * R[2];
270 
271  tempIntpts.y2 = intersection.x2 * R[3]
272  + intersection.y2 * R[4]
273  + intersection.z2 * R[5];
274 
275  tempIntpts.z2 = intersection.x2 * R[6]
276  + intersection.y2 * R[7]
277  + intersection.z2 * R[8];
278 
279  // Rotate any existing triple intersection pts to xy plane
280  Point tmpPt;
281  for (unsigned int i = 0; i<intersection.triplePointsIdx.size(); i++) {
282  tmpPt.x = triplePoints[intersection.triplePointsIdx[i]].x*R[0]
283  + triplePoints[intersection.triplePointsIdx[i]].y*R[1]
284  + triplePoints[intersection.triplePointsIdx[i]].z*R[2];
285 
286  tmpPt.y = triplePoints[intersection.triplePointsIdx[i]].x*R[3]
287  + triplePoints[intersection.triplePointsIdx[i]].y*R[4]
288  + triplePoints[intersection.triplePointsIdx[i]].z*R[5];
289 
290  tmpPt.z = triplePoints[intersection.triplePointsIdx[i]].x*R[6]
291  + triplePoints[intersection.triplePointsIdx[i]].y*R[7]
292  + triplePoints[intersection.triplePointsIdx[i]].z*R[8];
293 
294  tempTripPts.push_back(tmpPt);
295  }
296  }
297  else { // Already on xy plane (normal = {0,0,1}), no rotation required
298  // Copy triple points to tempIntpts
299  for (unsigned int i = 0; i < intersection.triplePointsIdx.size(); i++) {
300  int idx = intersection.triplePointsIdx[i];
301  tempTripPts.push_back(triplePoints[idx]);
302  }
303  tempIntpts.x1 = intersection.x1;
304  tempIntpts.y1 = intersection.y1;
305  tempIntpts.z1 = intersection.z1;
306  tempIntpts.x2 = intersection.x2;
307  tempIntpts.y2 = intersection.y2;
308  tempIntpts.z2 = intersection.z2;
309  }
310 
311  newPoly.XYPlane = 1; // Mark poly being rotated to xy plane
312  delete[] xProd; // xProd was created dynamically in crossProduct(), delete it
313  return tempIntpts;
314 }
315 
316 
317 /**********************************************************************/
318 /********************** Create Bounding box ***************************/
322 void createBoundingBox(struct Poly &newPoly) {
323  // Initialize mins and maxs
324  double maxX, minX, maxY, minY, maxZ, minZ;
325  maxX = minX = newPoly.vertices[0]; // x1
326  maxY = minY = newPoly.vertices[1]; // y1
327  maxZ = minZ = newPoly.vertices[2]; // z1
328 
329  for (int i = 1; i < newPoly.numberOfNodes; i++) {
330  int idx = i*3;
331  // idx = x
332  if (maxX < newPoly.vertices[idx]) {
333  maxX = newPoly.vertices[idx];
334  }
335  else if (minX > newPoly.vertices[idx]) {
336  minX = newPoly.vertices[idx];
337  }
338  // idx+1 = y
339  if (maxY < newPoly.vertices[idx+1]) {
340  maxY = newPoly.vertices[idx+1];
341  }
342  else if (minY > newPoly.vertices[idx+1]) {
343  minY = newPoly.vertices[idx+1];
344  }
345  // idx+2 = z
346  if (maxZ < newPoly.vertices[idx+2]) {
347  maxZ = newPoly.vertices[idx+2];
348  }
349  else if (minZ > newPoly.vertices[idx+2]) {
350  minZ = newPoly.vertices[idx+2];
351  }
352  }
353  newPoly.boundingBox[0] = minX;
354  newPoly.boundingBox[1] = maxX;
355  newPoly.boundingBox[2] = minY;
356  newPoly.boundingBox[3] = maxY;
357  newPoly.boundingBox[4] = minZ;
358  newPoly.boundingBox[5] = maxZ;
359 }
360 
361 
362 /**********************************************************************/
365 void printBoundingBox(struct Poly &newPoly) {
366  std::cout<<"\nBounding Box:\n";
367  std::cout<<"MinX = "<<newPoly.boundingBox[0]<<" MaxX = "<<newPoly.boundingBox[1]<<"\n";
368  std::cout<<"MinY = "<<newPoly.boundingBox[2]<<" MaxY = "<<newPoly.boundingBox[3]<<"\n";
369  std::cout<<"MinZ = "<<newPoly.boundingBox[4]<<" MaxZ = "<<newPoly.boundingBox[5]<<"\n";
370 }
371 
372 
373 /**********************************************************************/
374 /*********************** Check Bounding Box ***************************/
379 bool checkBoundingBox(Poly &poly1, Poly &poly2) {
380 
381  if (poly1.boundingBox[1] < poly2.boundingBox[0]) return false;
382  if (poly1.boundingBox[0] > poly2.boundingBox[1]) return false;
383  if (poly1.boundingBox[3] < poly2.boundingBox[2]) return false;
384  if (poly1.boundingBox[2] > poly2.boundingBox[3]) return false;
385  if (poly1.boundingBox[5] < poly2.boundingBox[4]) return false;
386  if (poly1.boundingBox[4] > poly2.boundingBox[5]) return false;
387  return true;
388 }
389 
390 
391 /**********************************************************************/
392 /****************** Find Intersections ********************************/
399 struct IntPoints findIntersections(short &flag, Poly &poly1, Poly &poly2) {
400 /* FLAGS: 0 = no intersection
401  NOTE: The only flag which is currently used is '0'
402  1 = intersection is completely inside poly 1 (new fracture)/poly)
403  2 = intersection is completely inside poly 2 (already accepted poly)
404  3 = intsersection on both polys edges
405  current implimentation: poly1 is the new fracture being tested
406  poly2 is a previously accepted fracture newPoly is being tested against
407 */
408 
409 // This code is mostly converted directly from the mathematica version.
410 // Re-write may be worth doing for increased performance and code clarity
411 
412  flag = 0;
413  IntPoints intPts; // Final intersection points
414 
415  int count;
416  Poly *F1; // Fracture 1
417  Poly *F2; // Fracture 2
418  double inters2[6]; // Temporary intersection points of F2 and P1
419  double inters[12]; // Stores 4 possible intersection points {x,y,z} * 3
420  double temp[3];
421 
422  // Get intersecction points
423  for (int jj = 0; jj<2; jj++) {
424  count = 0; // Intersection point number
425  if (jj == 0 ) {
426  F1 = &poly1;
427  F2 = &poly2;
428  }
429  else {
430  F1 = &poly2;
431  F2 = &poly1;
432  }
433  int nVertices2 = F2->numberOfNodes;
434  int index = (nVertices2-1) * 3; // Index to last vertice
435 
436  double vertex1[3] = { F1->vertices[0], F1->vertices[1], F1->vertices[2] };
437 
438  temp[0] = F2->vertices[index] - vertex1[0]; // x1 -x2
439  temp[1] = F2->vertices[index+1] - vertex1[1]; // y1 - y2
440  temp[2] = F2->vertices[index+2] - vertex1[2]; // z1 - z2
441 
442  double prevdist = dotProduct(temp, F1->normal);
443  double currdist;
444 
445  for (int i = 0; i < nVertices2; i++) { // i: current point
446  int idx = i * 3;
447  /* vector of vertex1 to a vertex on F2 dot normal vector of F1
448  it's absolute value is the distance */
449  temp[0] = F2->vertices[idx] - vertex1[0];
450  temp[1] = F2->vertices[idx+1] - vertex1[1];
451  temp[2] = F2->vertices[idx+2] - vertex1[2];
452  currdist = dotProduct(temp, F1->normal);
453 
454  if (std::abs(prevdist) < eps) {
455  if (i == 0) {
456  // Previous point is intersection point
457  inters2[0] = F2->vertices[index]; // x
458  inters2[1] = F2->vertices[index+1]; // y
459  inters2[2] = F2->vertices[index+2]; // z
460  count++;
461  }
462  else {
463  int idx = (i-1)*3;
464  int countidx = count*3;
465  inters2[countidx] = F2->vertices[idx]; // x
466  inters2[countidx+1] = F2->vertices[idx+1]; // y
467  inters2[countidx+2] = F2->vertices[idx+2]; // z
468  count++;
469  }
470  }
471  else {
472  double currTimesPrev = currdist * prevdist;
473  if (std::abs(currTimesPrev) < eps) {
474  currTimesPrev = 0;
475  }
476 
477  if (currTimesPrev < 0) {
478  // If consecutive vertices of F2 are at opposide sides of P1,
479  // computes intersection point of F2 and P1
480 
481  double c = std::abs(prevdist)/(std::abs(currdist)+std::abs(prevdist));
482  int countidx = count * 3;
483  if(i == 0) {
484  inters2[countidx] = F2->vertices[index]
485  + (F2->vertices[0]-F2->vertices[index]) * c;
486  inters2[countidx+1] = F2->vertices[index+1]
487  + (F2->vertices[1]-F2->vertices[index+1]) * c;
488  inters2[countidx+2] = F2->vertices[index+2]
489  + (F2->vertices[2]-F2->vertices[index+2]) * c;
490  count++;
491  }
492  else {
493  int idx = (i-1) * 3;
494  int x = i*3;
495  inters2[countidx] = F2->vertices[idx]
496  + (F2->vertices[x]-F2->vertices[idx]) * c;
497  inters2[countidx+1] = F2->vertices[idx+1]
498  + (F2->vertices[x+1]-F2->vertices[idx+1]) * c;
499  inters2[countidx+2] = F2->vertices[idx+2]
500  + (F2->vertices[x+2]-F2->vertices[idx+2]) * c;
501  count++;
502  }
503  }
504  }
505  prevdist = currdist;
506  if (count == 2) {
507  break; }
508 
509  } // End vertice loop
510 
511  if (count == 1) {
512  // If only one intersection point, happens only when a vertex of F2 is on P1
513  count = 2;
514  inters2[3] = inters2[0];
515  inters2[4] = inters2[1];
516  inters2[5] = inters2[2];
517  }
518 
519  for (int k = 0; k<6; k++) {
520  if (std::abs(inters2[k]) < eps) {
521  inters2[k] = 0; }
522  }
523 
524  // copy to inters array
525  int jindx = 6*jj;
526  inters[jindx] = inters2[0];
527  inters[jindx+1] = inters2[1];
528  inters[jindx+2] = inters2[2];
529  inters[jindx+3] = inters2[3];
530  inters[jindx+4] = inters2[4];
531  inters[jindx+5] = inters2[5];
532 
533  if (count == 0) {
534  break;
535  } // No intersection
536  } // End loop for jj, loop for getting intersections for fracture i and newPoly
537 
538  if (count == 0) {
539  flag = 0;
540  }
541  else { // Intersection points exist
542  if (count >2) { std::cout<<"Error in findIntersections()\n"; }
543 
544  // Use delete[] on 'stdev', created dynamically
545  double *stdev = sumDevAry3(inters);
546 
547  int o = maxElmtIdx(stdev,3);
548 
549  double tempAry[4] = {inters[o], inters[o+3], inters[o+6], inters[o+9]};
550 
551  int *s = sortedIndex(tempAry,4);
552 
553  if (!(s[0] + s[1] == 1 || s[0] + s[1] == 5)) {
554  // If the smallest two points are not on the bdy of the same poly,
555  // the polygons intersect. middle two points form intersetion
556 
557  int idx1 = s[1]*3;
558  int idx2 = s[2]*3;
559 
560  intPts.x1 = inters[idx1]; // x1
561  intPts.y1 = inters[idx1+1]; // y1
562  intPts.z1 = inters[idx1+2]; // z1
563  intPts.x2 = inters[idx2]; // x2
564  intPts.y2 = inters[idx2+1]; // y2
565  intPts.z2 = inters[idx2+2]; // z2
566 
567  // Assign flag (definitions at top of funciton)
568  if (s[1] + s[2] == 1) {
569  flag = 1;} // Intersection inside poly1
570  else if (s[1] + s[2] == 5 ) {
571  flag = 2;} // Intersection inside poly2
572  else{
573  flag = 3;} // Intersection on edges
574  }
575  else { // Intersection doesn't exist
576  flag = 0; // No intersection
577  }
578 
579  delete[] s;
580  delete[] stdev;
581 
582  } // End intersection points exist
583  return intPts;
584 }
585 
586 
587 /*************************************************************************************/
588 /*************************************************************************************/
589 /************************************ FRAM *******************************************/
590 /******************** Feature Rejection Algorithm for Meshing ************************/
607 int FRAM(IntPoints &intPts, unsigned int count, std::vector<IntPoints> &intPtsList, Poly &newPoly, Poly &poly2, Stats &pstats, std::vector<TriplePtTempData> &tempData, std::vector<Point> &triplePoints, std::vector<IntPoints> &tempIntPts) {
608 
609  if (disableFram == false) {
610  /******* Check for intersection of length less than h *******/
611  if (magnitude(intPts.x1-intPts.x2, intPts.y1-intPts.y2, intPts.z1-intPts.z2) < h) {
612  //std::cout<<"\nrejectCode = -2: Intersection of length <= h.\n";
614  return -2;
615  }
616 
617  /******************* distance to edges *****************/
618  // Reject if intersection shirnks < 'shrinkLimit'
619  double shrinkLimit = 0.9 * magnitude(intPts.x1 - intPts.x2, intPts.y1 - intPts.y2, intPts.z1 - intPts.z2);
620  if (checkCloseEdge(newPoly, intPts, shrinkLimit, pstats)) {
621  // std::cout<<"\nrejectCode = -6: Fracture too close to another fracture's edge.\n";
622  pstats.rejectionReasons.closeToEdge++;
623  return -6;
624  }
625 
626  if (checkCloseEdge(poly2, intPts, shrinkLimit, pstats)) {
627  // std::cout<<"\nrejectCode = -6: Fracture too close to another fracture's edge.\n";
628  pstats.rejectionReasons.closeToEdge++;
629  return -6;
630  }
631  /*************** Triple Intersection Checks *************/
632  // NOTE: for debugging, there are several rejection codes for triple intersections
633  // -14 <= rejCode <= -10 are for triple intersection rejections
634 
635  int rejCode = checkForTripleIntersections(intPts, count, intPtsList, newPoly, poly2, tempData, triplePoints);
636  if (rejCode != 0 ) {
637  pstats.rejectionReasons.triple++;
638  return rejCode;
639  }
640 
641  /******* Intersection to Intersection Distance Checks ********/
642  // Check distance from new intersection to other intersections on
643  // poly2 (fracture newPoly is intersecting with)
644 
645  if (checkDistToOldIntersections(intPtsList, intPts, poly2, h)) {
647  return -5;
648  }
649 
650  // Check distance from new intersection to intersections already
651  // existing on newPoly
652  // Also checks for undetected triple points
653  if (checkDistToNewIntersections(tempIntPts, intPts, tempData, h)) {
655  return -5;
656  }
657 
658  // Check if polys intersect on same plane
659  if (std::abs(newPoly.normal[0]-poly2.normal[0]) < eps // If the normals are the same
660  && std::abs(newPoly.normal[1]-poly2.normal[1]) < eps
661  && std::abs(newPoly.normal[2]-poly2.normal[2]) < eps ) {
662 
663  return -7; // The intersection has already been found so we know that if the
664  // normals are the same they must be on the same plane
665  }
666  }
667  return 0;
668 }
669 
670 
671 /**************************** FRAM CHECK *****************************************/
672 /************ New intersction to Old Intersections Check ***************************/
680 bool checkDistToOldIntersections(std::vector<IntPoints> &intPtsList, IntPoints &intPts, Poly &poly2, double minDistance) {
681  double intersection[6] = {intPts.x1, intPts.y1, intPts.z1, intPts.x2, intPts.y2, intPts.z2};
682  int intSize = poly2.intersectionIndex.size();
683  double dist;
684  Point pt;
685  for (int i = 0; i < intSize; i ++) {
686 
687  double int2[6] = {intPtsList[poly2.intersectionIndex[i]].x1, intPtsList[poly2.intersectionIndex[i]].y1, intPtsList[poly2.intersectionIndex[i]].z1,
688  intPtsList[poly2.intersectionIndex[i]].x2, intPtsList[poly2.intersectionIndex[i]].y2, intPtsList[poly2.intersectionIndex[i]].z2};
689 
690  dist = lineSegToLineSeg(intersection, int2, pt);
691  if (dist < (minDistance-eps) && dist > eps) {
692  return 1;
693  }
694  }
695  return 0;
696 }
697 
698 
699 /**************************** FRAM Check *****************************************/
700 /************ New intersction to New Intersections Check ***************************/
712 bool checkDistToNewIntersections(std::vector<IntPoints> &tempIntPts, IntPoints &intPts, std::vector<TriplePtTempData> &tempTriPts, double minDistance) {
713 
714  int intSize = tempIntPts.size();
715  double intersection[6] = {intPts.x1, intPts.y1, intPts.z1, intPts.x2, intPts.y2, intPts.z2};
716  Point pt; // Pt of intersection if lines intersect
717 
718  for (int i = 0; i < intSize; i ++) {
719 
720  double int2[6] = {tempIntPts[i].x1, tempIntPts[i].y1, tempIntPts[i].z1,
721  tempIntPts[i].x2, tempIntPts[i].y2, tempIntPts[i].z2};
722 
723  double dist = lineSegToLineSeg(intersection, int2, pt);
724 
725  if (dist < minDistance && dist > eps) {
726  return 1;
727  }
728  else if (dist < eps) {
729  // Make sure there is a triple intersection point
730  // before accepting
731  bool reject = true;
732  int size = tempTriPts.size();
733  for (int i = 0; i < size; i++) {
734  // If the triple point is found, continue with checks, else reject
735  if (std:: abs(pt.x - tempTriPts[i].triplePoint.x) < eps
736  && std::abs(pt.y - tempTriPts[i].triplePoint.y) < eps
737  && std::abs(pt.z - tempTriPts[i].triplePoint.z) < eps) {
738  reject = false;
739  break;
740  }
741  }
742  if (reject == true) {
743  return 1;
744  }
745  }
746  }
747  return 0;
748 }
749 
750 /**********************************************************************/
751 /************************* Shrink Intersection ************************/
770 bool shrinkIntersection(IntPoints &intPts, double *edge, double shrinkLimit, double firstNodeMinDist, double minDist) {
771 
772  double vect[3] = {(intPts.x2-intPts.x1), (intPts.y2-intPts.y1), (intPts.z2-intPts.z1)};
773  double dist = magnitude(vect[0], vect[1], vect[2]);
774 
775  // n is number of discrete points on intersection
776  int n = std::ceil(2 * dist / h);
777  double stepSize = 1 / (double)n;
778 
779  double pt[3] = {intPts.x1, intPts.y1, intPts.z1};
780 
781  // Start step at first descrete point
782  double step;
783 
784  // Check both sides of intersection against edge
785  for (int i = 0; i < 2; i++) {
786  int nodeCount = 0;
787 
788  if (i == 0) {
789  step = 0;
790  }
791  else {
792  step = 1;
793  }
794 
795  Point point = lineFunction3D(vect, pt, step);
796  double firstPtDistToEdge = pointToLineSeg(point, edge);
797 
798  bool firstPt = true;
799  while (nodeCount <= n) {
800  nodeCount++;
801 
802  if (i == 0) {
803  step += stepSize;
804  }
805  else {
806  step -= stepSize;
807  }
808 
809  Point ptOnIntersection = lineFunction3D(vect, pt, step);
810 
811  double dist = pointToLineSeg(ptOnIntersection, edge);
812  if (firstPt == true && (dist > firstNodeMinDist)) { // || (stepSize == 1 && dist < eps))) {
813  if (firstPtDistToEdge < eps || firstPtDistToEdge >= minDist) {
814  // Leave intersection end point un-modified
815  break;
816  }
817  }
818 
819  firstPt = false;
820 
821  if (dist > minDist) {
822  if (i == 0) {
823  intPts.x1 = ptOnIntersection.x;
824  intPts.y1 = ptOnIntersection.y;
825  intPts.z1 = ptOnIntersection.z;
826  }
827  else {
828  intPts.x2 = ptOnIntersection.x;
829  intPts.y2 = ptOnIntersection.y;
830  intPts.z2 = ptOnIntersection.z;
831 
832  }
833  intPts.intersectionShortened = true;
834  break;
835  }
836  if (nodeCount >= n) { // All nodes are bad, reject
837  return 1;
838  }
839  }
840  }
841 
842  // If intersection length shrank to less than shrinkLimit, reject
843  if (magnitude(intPts.x2-intPts.x1, intPts.y2-intPts.y1, intPts.z2-intPts.z1) < shrinkLimit) {
844  return 1;
845  }
846 
847  return 0;
848 }
849 
850 
851 /****************************************************************************************************/
852 /************************************** INTERSECTION CHECKING ***************************************/
870 int intersectionChecking(struct Poly &newPoly, std::vector<Poly> &acceptedPoly, std::vector<IntPoints> &intPtsList, struct Stats &pstats, std::vector<Point> &triplePoints) {
871 
872  // List of fractures which new fracture intersected.
873  // Used to update fractures intersections and
874  // intersection count if newPoly is accepted
875  std::vector<unsigned int> tempIntersectList;
876  std::vector<IntPoints> tempIntPts;
877  std::vector<IntPoints> tempOriginalIntersection;
878  // Index to newPoly's position if accepted
879  int newPolyIndex = acceptedPoly.size();
880  // Index to intpts if newPoly intersections accepted
881  int intPtsIndex = intPtsList.size();
882  std::vector<unsigned int> encounteredGroups;
883  // Counts number of accepted intersections on newPoly.
884  unsigned int count = 0;
885  std::vector<TriplePtTempData> tempData;
886 
887 
888  unsigned int size = acceptedPoly.size();
889  for (unsigned int ii = 0; ii < size; ii++) {
890  short flag;
891 
892  // NOTE: findIntersections() searches bounding boxes
893  // Bounding box search
894  if (checkBoundingBox(newPoly, acceptedPoly[ii])) {
895  IntPoints intersection = findIntersections(flag, newPoly, acceptedPoly[ii]);
896 
897  if (flag != 0) { // If flag != 0, intersection exists
898  // Holds origintal intersection, used to update
899  // stats on how much intersections were shortened
900  tempOriginalIntersection.push_back(intersection);
901 
902  // FRAM returns 0 if no intersection problems.
903  // 'count' is number of already accepted intersections on new poly
904 
905  int rejectCode = FRAM(intersection, count, intPtsList, newPoly, acceptedPoly[ii], pstats, tempData, triplePoints, tempIntPts);
906 
907  // If intersection is NOT rejected
908  if (rejectCode == 0) { // If FRAM returned 0, everything is OK
909 
910  // Update group numbers, intersection indexes
911  intersection.fract1 = ii; // ii is the intersecting fracture
912  intersection.fract2 = newPolyIndex; // newPolys ID/index in array of accpted polys, if accepted
913 
914  // 'tempIntersectList' keeps all fracture #'s intersecting with newPoly
915  tempIntersectList.push_back(ii); // Save fracture index to update if newPoly accepted
916 
917  // Save index to polys intersections (intPts) array
918  newPoly.intersectionIndex.push_back(intPtsIndex + count);
919 
920  count++; // Increment counter of number of fractures intersecting with newPoly
921  tempIntPts.push_back(intersection); // Save intersection
922 
923  // If newPoly has not been assigned to a group,
924  // assign the group of the other intersecting fracture
925  if (newPoly.groupNum == 0) {
926  newPoly.groupNum = acceptedPoly[ii].groupNum;
927  }
928  else if (newPoly.groupNum != acceptedPoly[ii].groupNum) { // Poly bridged two different groupsa
929  encounteredGroups.push_back(acceptedPoly[ii].groupNum);
930  }
931  }
932  else { // 'newPoly' rejected
933  // SAVE REJECTED POLYS HERE IF THIS FUNCTINALITY IS NEEDED
934  return rejectCode; // Break loop/function and return 1, poly is rejected
935  }
936  }
937  }
938  } // If it makes it here, no problematic intersections with new polygon. SAVE POLY AND UPDATE GROUP/CLUSTER INFO
939 
940 
941  // Done searching intersections. All FRAM tests have passed. Polygon is accetepd.
942 
943 
944  // After searching for intersections, if newPoly still has no intersection or group:
945  if (newPoly.groupNum == 0) { // 'newPoly' had no intersections. Assign it to its own/new group number
946  assignGroup(newPoly, pstats, newPolyIndex);
947  }
948  else {
949  // Intersections exist and were accepted, newPoly already has group number
950  // Save temp. intersections to intPts (permanent array),
951  // Update all intersected polygons intersection-points index lists and intersection count
952  // Update polygon group lists
953 
954  // Append temp intersection points array to permanent one
955  intPtsList.insert(intPtsList.end(),tempIntPts.begin(),tempIntPts.end());
956 
957  // Update poly's indexs to intersections list (intpts)
958  for (unsigned int i = 0; i < tempIntersectList.size(); i++) {
959  // Update each intersected poly's intersection index
960 
961  acceptedPoly[tempIntersectList[i]].intersectionIndex.push_back(intPtsIndex + i);
962  // intPtsIndex+i will be the index position of the intersection once it is saved to the intersections array
963  }
964 
965  // Fracture is now accepted.
966  // Update intersection structures with triple intersection points.
967  // triple intersection points will be found 3 times (3 fractures make up one triple int point)
968  // We need only to save the point to the permanent triplePoints array once, and then give each intersection a
969  // reference to it.
970  if (tripleIntersections == 1) {
971  unsigned int tripIndex = triplePoints.size();
972  for (unsigned int j = 0; j < tempData.size(); j++) { // Loop through newly found triple points
973 
974  triplePoints.push_back(tempData[j].triplePoint);
975 
976  // Update index pointers to the triple intersection points
977  for (unsigned int ii = 0; ii < tempData[j].intIndex.size(); ii++) {
978  unsigned int idx = tempData[j].intIndex[ii];
979  intPtsList[idx].triplePointsIdx.push_back(tripIndex + j);
980  }
981  }
982  }
983 
984  // ***********************
985  // Update group numbers **
986  // ***********************
987  updateGroups(newPoly, acceptedPoly, encounteredGroups, pstats, newPolyIndex);
988  }
989 
990  // Keep track of how much intersection length we are looising from 'shrinkIntersection()'
991  // Calculate and store total original intersection length (all intersections)
992  // and actual intersection length, after intersection has been shortened.
993  for (unsigned int i = 0; i < tempIntPts.size(); i++) {
994  double length = magnitude(tempOriginalIntersection[i].x1 - tempOriginalIntersection[i].x2,
995  tempOriginalIntersection[i].y1 - tempOriginalIntersection[i].y2,
996  tempOriginalIntersection[i].z1 - tempOriginalIntersection[i].z2);
997 
998  pstats.originalLength += length;
999 
1000  if (tempIntPts[i].intersectionShortened == true) {
1001  pstats.intersectionsShortened++;
1002 
1003  double newLength = magnitude(tempIntPts[i].x1 - tempIntPts[i].x2,
1004  tempIntPts[i].y1 - tempIntPts[i].y2,
1005  tempIntPts[i].z1 - tempIntPts[i].z2);
1006 
1007  pstats.discardedLength += length - newLength;
1008  }
1009  }
1010  return 0;
1011 }
1012 
1013 
1014 /********************************************************************************************/
1015 /* Disatance from intersection line to Nodes/Vertices *************************************/
1022 bool checkDistanceFromNodes(struct Poly &poly, IntPoints &intPts, double minDist, Stats &pstats) {
1023  int nNodes = poly.numberOfNodes;
1024  double dist;
1025 
1026  // Intersection dist to poly vertices
1027  double line[6] = {intPts.x1, intPts.y1, intPts.z1, intPts.x2, intPts.y2, intPts.z2};
1028  dist = pointToLineSeg(poly.vertices, line);
1029 
1030  for (int i = 1; i < nNodes; i++) {
1031  int idx = 3*i;
1032  double temp = pointToLineSeg(&poly.vertices[idx], line);
1033 
1034  // If new distance is less than the last calculated distance...
1035  if (temp < dist) {
1036  dist = temp;
1037  }
1038  if (dist < minDist && dist > eps) {
1039  pstats.rejectionReasons.closeToNode++;
1040  return 1;
1041  }
1042  }
1043 
1044  // If it makes it here, no distance less than 'minDist' found
1045  return 0;
1046 }
1047 
1048 
1049 /********************************************************************************/
1050 /******************** Shortest Disatance, point to line seg *********************/
1054 double pointToLineSeg(const double *point, const double *line) {
1055  const double sqrLineLen = sqrMagnitude(line[0]-line[3], line[1]-line[4], line[2]-line[5]); // i.e. |w-v|^2 - avoid a sqrt
1056  if (sqrLineLen < eps) {
1057  // Line endpoints are equal to each other
1058  return magnitude(point[0]-line[0], point[1]-line[1], point[2]-line[2]);
1059  }
1060 
1061  double pL1[3] = { point[0]-line[0], point[1]-line[1], point[2]-line[2] };
1062  double L1L2[3] = { line[3]-line[0], line[4]-line[1], line[5]-line[2] };
1063 
1064  // Find parameterization for line projection on [0, 1]
1065  const double t = std::max(0.0, std::min(1.0, dotProduct(pL1, L1L2) / sqrLineLen));
1066 
1067  double projection[3] = { t * L1L2[0], t * L1L2[1], t * L1L2[2] };
1068  projection[0] += line[0];
1069  projection[1] += line[1];
1070  projection[2] += line[2];
1071 
1072  return magnitude(projection[0]-point[0], projection[1]-point[1], projection[2]-point[2]);
1073 }
1074 
1075 // Overloaded function
1079 double pointToLineSeg(const Point &point, const double *line) {
1080  const double sqrLineLen = sqrMagnitude(line[0]-line[3], line[1]-line[4], line[2]-line[5]); // i.e. |w-v|^2 - avoid a sqrt
1081  if (sqrLineLen < eps) {
1082  // Line endpoints are equal to each other
1083  return magnitude(point.x-line[0], point.y-line[1], point.z-line[2]);
1084  }
1085 
1086  double pL1[3] = { point.x-line[0], point.y-line[1], point.z-line[2] };
1087  double L1L2[3] = { line[3]-line[0], line[4]-line[1], line[5]-line[2] };
1088 
1089  // Find parameterization for line projection on [0, 1]
1090  const double t = std::max(0.0, std::min(1.0, dotProduct(pL1, L1L2) / sqrLineLen));
1091 
1092  double projection[3] = { t * L1L2[0], t * L1L2[1], t * L1L2[2] };
1093  projection[0] += line[0];
1094  projection[1] += line[1];
1095  projection[2] += line[2];
1096 
1097  return magnitude(projection[0]-point.x, projection[1]-point.y, projection[2]-point.z);
1098 }
1099 
1100 
1101 /*******************************************************************************/
1102 /************************* Is Point On Line Segment ****************************/
1108 bool pointOnLineSeg(const double *pt, const double *line) {
1109 
1110  // A = end pt 1, B = end pt 2,
1111  // pt is point we are checking if on line between A and B
1112  // If mag(A to Pt) + mag(pt to B) = mag(A to B), pt is on line
1113 
1114  // end point A to end point B
1115  double temp[3] = { line[3]-line[0], line[4]-line[1], line[5]-line[2] };
1116 
1117  double endPttoEndPt_Dist = std::sqrt(temp[0] * temp[0] + temp[1] * temp[1] + temp[2] * temp[2]);
1118 
1119  // end point A to pt
1120  temp[0] = pt[0] - line[0];
1121  temp[1] = pt[1] - line[1];
1122  temp[2] = pt[2] - line[2];
1123 
1124  double endPtToPt_Dist = std::sqrt(temp[0] * temp[0] + temp[1] * temp[1] + temp[2] * temp[2]);
1125 
1126  // pt to end pt B
1127  temp[0] = line[3] - pt[0];
1128  temp[1] = line[4] - pt[1];
1129  temp[2] = line[5] - pt[2];
1130 
1131  double ptToEndPt_Dist = std::sqrt(temp[0] * temp[0] + temp[1] * temp[1] + temp[2] * temp[2]);
1132 
1133  // (end pt A to pt) + (pt to end pt B) - (end pt to end pt)
1134  // If zero, pt is between endpoints, and on line
1135  double result = endPtToPt_Dist + ptToEndPt_Dist - endPttoEndPt_Dist;
1136  if (-eps < result && result < eps) {
1137  return true;
1138  }
1139  return false;
1140 }
1141 
1142 
1143 // Overloaded function
1144 /********************************************************************************/
1145 /************************* Is Point On Line Segment ****************************/
1151 bool pointOnLineSeg(const Point &pt, const double *line) {
1152 
1153  // A = end pt 1, B = end pt 2,
1154  // pt is point we are checking if on line between A and B
1155  // If mag(A to Pt) + mag(pt to B) = mag(A to B), pt is on line
1156 
1157  //end point A to end point B
1158  double temp[3] = { line[3]-line[0], line[4]-line[1], line[5]-line[2] };
1159 
1160  double endPttoEndPt_Dist = std::sqrt(temp[0] * temp[0] + temp[1] * temp[1] + temp[2] * temp[2]);
1161 
1162  //end point A to pt
1163  temp[0] = pt.x - line[0];
1164  temp[1] = pt.y - line[1];
1165  temp[2] = pt.z - line[2];
1166 
1167  double endPtToPt_Dist = std::sqrt(temp[0] * temp[0] + temp[1] * temp[1] + temp[2] * temp[2]);
1168 
1169  //pt to end pt B
1170  temp[0] = line[3] - pt.x;
1171  temp[1] = line[4] - pt.y;
1172  temp[2] = line[5] - pt.z;
1173 
1174  double ptToEndPt_Dist = std::sqrt(temp[0] * temp[0] + temp[1] * temp[1] + temp[2] * temp[2]);
1175 
1176  // (end pt A to pt) + (pt to end pt B) - (end pt to end pt)
1177  // if zero, pt is between and on line
1178  double result = endPtToPt_Dist + ptToEndPt_Dist - endPttoEndPt_Dist;
1179  if (-eps < result && result < eps) {
1180  return true;
1181  }
1182  return false;
1183 }
1184 
1185 
1186 /********************************************************************************/
1187 /****************** Check if nodes are too close to edge ************************/
1197 bool checkCloseEdge(Poly &poly1, IntPoints &intPts, double shrinkLimit, Stats &pstats) {
1198 
1199  // 'line' is newest intersection end points
1200  double line[6] = {intPts.x1, intPts.y1, intPts.z1, intPts.x2, intPts.y2, intPts.z2};
1201 
1202  // minDist is the minimum distance allowed from an end point to the edge of a polygon
1203  // if the intersection does not land accross a poly's edge
1204  double minDist = h;
1205 
1206  // Counts how many endPoints are on the polys edge.
1207  // If both end points of intersection are on polys edge,
1208  // we must check the distance from end points to
1209  // vertices
1210  int onEdgeCount = 0;
1211 
1212  for (int i = 0; i < poly1.numberOfNodes; i++) {
1213  int next;
1214  int idx = 3*i;
1215 
1216  if (i != poly1.numberOfNodes -1) {
1217  next = (i+1)*3;
1218  }
1219  else{ // If last edge on polygon
1220  next = 0;
1221  }
1222 
1223  // Edge is two points, x y and z coords of poly vertices
1224  double edge[6] = {poly1.vertices[idx],poly1.vertices[idx+1],poly1.vertices[idx+2],
1225  poly1.vertices[next], poly1.vertices[next+1], poly1.vertices[next+2]};
1226  Point pt; // 'pt' is point of intersection, set in lineSegToLineSeg()
1227 
1228  // Get distances of each point to line
1229  double endPtsToEdge[4] = { pointToLineSeg(&line[0], edge), pointToLineSeg(&line[3], edge),
1230  pointToLineSeg(&edge[0], line), pointToLineSeg(&edge[3], line) };
1231 
1232  // Sort smallest to largest
1233  std::sort(endPtsToEdge, endPtsToEdge + 4);
1234 
1235  // If two smallest distances are < h,
1236  // the line is almost parallel and closer to edge than h, reject it
1237  if ((endPtsToEdge[0] < h && endPtsToEdge[1] < h) && endPtsToEdge[0] > eps) {
1238  return 1;
1239  }
1240 
1241  // Minimum dist from poly edge segment to intersection segment
1242  double dist = lineSegToLineSeg(edge, line, pt);
1243 
1244  if (dist < minDist && dist > eps) {
1245  // Try to shrink the intersection slightly in order to
1246  // not reject the polygon
1247  if (shrinkIntersection(intPts, edge, shrinkLimit, h, h) == 1) {
1248  // Returns one if insterection shrinks to less than .9*h
1249  return 1;
1250  }
1251  }
1252  else if (dist < eps) {
1253  // Endpoint is almost exactly on poly's edge, must check
1254  // whether the discretized nodes will ne closer
1255  // than the minimum allowed distance
1256  // shrinkIntersection() will check if the descretized intersection points violate any
1257  // distance to edge rules
1258  // NOTE: Intersections discretize with set size = .5*h
1259  // Minimum distance to edge must be less than .5*h to allow for angles
1260  const static double minDist2 = 0.4 * h;
1261  if (shrinkIntersection(intPts, edge, shrinkLimit, minDist2, h) == 1) {
1262  //returns one if insterection shrinks to less than .9*h
1263  return 1;
1264  }
1265 
1266  onEdgeCount++;
1267 
1268  // If both end points are on the edge we must also check the distnace
1269  // of the intersection to the poly vertices.
1270  // IF the intersecion is within the polygon, distances less than h to
1271  // edges and vertices will be caught by lineSegToLineSeg() in this function.
1272  if (onEdgeCount >= 2) {
1273 
1274  if (checkDistanceFromNodes(poly1, intPts, h, pstats)) {
1275  return 1;
1276  }
1277  }
1278  }
1279 
1280  }
1281  #ifdef DISABLESHORTENINGINT
1282  if (intPts.intersectionShortened == true) {
1283  return 1;
1284  }
1285  #endif
1286 
1287  return 0;
1288 }
1289 
1290 
1291 /********************************************************************************/
1292 /***************** Find point of intersection between two lines ****************/
1302 Point lineIntersection3D(const double *p1, double *v1, const double *p2, double *v2) {
1303  normalize(v1);
1304  normalize(v2);
1305 
1306  double v1xv2[3] = {(v1[1]*v2[2])-(v1[2]*v2[1]), (v1[2]*v2[0])-(v1[0]*v2[2]), (v1[0]*v2[1])-(v1[1]*v2[0])};
1307  double denom = dotProduct(v1xv2, v1xv2);
1308  double v21[3] = {p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]};
1309  double v21xv2[3] = {(v21[1]*v2[2])-(v21[2]*v2[1]), (v21[2]*v2[0])-(v21[0]*v2[2]), (v21[0]*v2[1])-(v21[1]*v2[0])};
1310  double temp[3];
1311  double temp2 = dotProduct(v21xv2, v1xv2);
1312  double temp3 = temp2/denom;
1313  temp[0] = v1[0]*temp3;
1314  temp[1] = v1[1]*temp3;
1315  temp[2] = v1[2]*temp3;
1316 
1317  Point pt;
1318  pt.x = temp[0] + p1[0];
1319  pt.y = temp[1] + p1[1];
1320  pt.z = temp[2] + p1[2];
1321 
1322  return pt;
1323 }
1324 
1325 
1326 /********************************************************************************/
1327 /************ Closest Distance from Line Seg to Line Seg ***********************/
1338 double lineSegToLineSeg(const double *line1, const double *line2, Point &pt) {
1339 
1340  // Check if line 1 and line 2 intersect
1341  const double p1[3] = {line1[0], line1[1], line1[2]};
1342  const double p2[3] = {line2[0], line2[1], line2[2]};
1343  double v1[3];
1344  v1[0] = line1[0] - line1[3];
1345  v1[1] = line1[1] - line1[4];
1346  v1[2] = line1[2] - line1[5];
1347  double v2[3];
1348  v2[0] = line2[0] - line2[3];
1349  v2[1] = line2[1] - line2[4];
1350  v2[2] = line2[2] - line2[5];
1351 
1352  double p1p2[3] = {p1[0]-p2[0], p1[1]-p2[1], p1[2]-p2[2]};
1353 
1354  if(parallel(v1, v2)) {
1355  if(magnitude(p1p2[0], p1p2[1], p1p2[2]) < eps || parallel(p1p2, v1) == 1) {
1356  // If 2 line segs overlap
1357  if(pointOnLineSeg(line1, line2) == 1 || pointOnLineSeg(&line1[3], line2) == 1) {
1358  return 0;
1359  }
1360  else { // Line segs are colinear but not overlapping
1361  return lineSegToLineSegSep(line1, line2);
1362  }
1363  }
1364  else {// Line segs are parallel but not overlapping
1365  return lineSegToLineSegSep(line1, line2);
1366  }
1367  }
1368  else{ // Lines are not parallel
1369  pt = lineIntersection3D(p1, v1, p2, v2); // Point of intersection if lines intersect
1370  double temp[3] = {pt.x, pt.y, pt.z};
1371  if (pointOnLineSeg(temp, line1) && pointOnLineSeg(temp, line2)) { // Case 1: Lines Intersection occurs on the lines
1372  return 0;
1373  }
1374  else {// Case 2: Line Intersection does not occur on both lines, find min distance from 4 endpoints to other line seg
1375  return lineSegToLineSegSep(line1, line2);
1376  }
1377  }
1378 }
1379 
1380 /********************************************************************************/
1381 /********** Dist. from line seg to line seg (seperated lines) *******************/
1389 double lineSegToLineSegSep(const double *line1, const double *line2) {
1390  double dist = std::min(pointToLineSeg(line1, line2), pointToLineSeg(&line1[3], line2));
1391  double temp = std::min(pointToLineSeg(line2, line1), pointToLineSeg(&line2[3], line1));
1392 
1393  if (dist < temp) return dist;
1394  else return temp;
1395 }
1396 
1397 
1398 /********************************************************************************/
1399 /************** Check for Triple Intersection , get int. point ******************/
1400 /********************************************************************************/
1412 int checkForTripleIntersections(IntPoints &intPts, unsigned int count, std::vector<IntPoints> &intPtsList, Poly &newPoly, Poly &poly2, std::vector<TriplePtTempData> &tempData, std::vector<Point> &triplePoints) {
1413 
1414  Point pt;
1415  double minDist = 1.5*h;
1416  double intEndPts[6] = {intPts.x1, intPts.y1, intPts.z1, intPts.x2, intPts.y2, intPts.z2};//newest intersection
1417 
1418  // Number of intersections already on poly2
1419  int n = poly2.intersectionIndex.size();
1420  // Check new fracure's new intesrsection against previous intersections on poly2
1421  for (int i = 0; i < n; i++) {
1422  unsigned int intersectionIndex = poly2.intersectionIndex[i]; // Index to previous intersecction (old intersection)
1423  unsigned int intersectionIndex2 = intPtsList.size() + count; // Index to current intersection, if accepted (new intersection)
1424 
1425  double line[6] = {intPtsList[intersectionIndex].x1, intPtsList[intersectionIndex].y1, intPtsList[intersectionIndex].z1, intPtsList[intersectionIndex].x2, intPtsList[intersectionIndex].y2, intPtsList[intersectionIndex].z2};
1426 
1427  double dist1 = lineSegToLineSeg(intEndPts, line, pt); //get distance and pt of intersection
1428 
1429  if (dist1 >= h) {
1430  continue;
1431  }
1432 
1433  if (tripleIntersections == 0 && dist1 < h) {
1434  return -10; // Triple intersections not allowed (user input option)
1435  }
1436 
1437  if (dist1 > eps && dist1 < h) {
1438  return -11; // Point too close to other intersection
1439  }
1440 
1441  // Overlaping intersections
1442  if (dist1 <= eps) {
1443  // ANGLE CHECK, using definition of dot product: A dot B = Mag(A)*Mag(B) * Cos(angle)
1444  // Normalize A and B first. Compare to precalculated values of cos(47deg)= .681998 and cos(133deg)= -.681998
1445  double U[3] = {line[3]-line[0], line[4]-line[1], line[5]-line[2]};
1446  double V[3] = {intPts.x2 - intPts.x1, intPts.y2 - intPts.y1, intPts.z2 - intPts.z1}; //endpoints
1447  normalize(U);
1448  normalize(V);
1449 
1450  double dotProd = dotProduct(U,V);
1451 
1452  if (dotProd < -0.68199836 || dotProd > 0.68199836) { //if angle is less than 47 deg or greater than 133, reject
1453  return -12;
1454  }
1455 
1456  // Check that the triple intersection point isn't too close to an endpoint
1457  double dist2;
1458  double point[3] = {pt.x, pt.y, pt.z}; // Triple intersection point
1459  dist1 = euclideanDistance(point,intEndPts);
1460  dist2 = euclideanDistance(point,&intEndPts[3]);
1461  if (dist1 < h || dist2 < h) {
1462  return -13;
1463  }
1464  dist1 = euclideanDistance(point,line);
1465  dist2 = euclideanDistance(point,&line[3]);
1466  if (dist1 < h || dist2 < h) {
1467  return -13;
1468  }
1469 
1470  // Check that the triple intersection point isn't too close to previous triple intersection points
1471  for(unsigned int k = 0; k < intPtsList[intersectionIndex].triplePointsIdx.size(); k++) {
1472  unsigned int idx = intPtsList[intersectionIndex].triplePointsIdx[k];
1473  double triplePt[3] = {triplePoints[idx].x, triplePoints[idx].y,triplePoints[idx].z};
1474  dist1 = euclideanDistance(point, triplePt);
1475  if (dist1 < minDist) {
1476  return -14;
1477  }
1478  }
1479 
1480  // Look at previously found triple points on current line of intersection,
1481  // do not save duplicate triple ponits
1482  // If duplicate point is found, a different intersection may still be needing an update
1483  // (three intersections per single triple intersection point )
1484  bool duplicate = 0;
1485  unsigned int k;
1486  // See if the found triple pt is already saved
1487  for (k = 0; k < tempData.size(); k++) {
1488  if (std::abs(pt.x - tempData[k].triplePoint.x) < eps
1489  && std::abs(pt.y - tempData[k].triplePoint.y) < eps
1490  && std::abs(pt.z - tempData[k].triplePoint.z) < eps) {
1491  duplicate = 1;
1492  break;
1493  }
1494  }
1495 
1496  // If it is a duplicate triple pt
1497  if (duplicate == 1) {
1498  // The old fracture's intersection needs
1499  // a reference to the new triple int pt
1500  // Save the index to the old fractures intersection
1501  // which needs updating. If newPoly is accpted
1502  // the old fracture will be updated
1503  tempData[k].intIndex.push_back(intersectionIndex2);
1504  }
1505  else{ // Not a duplicate point
1506  // Save temp triple point data, store to permanent at end if fracture is accepted
1507  TriplePtTempData localTemp;
1508  localTemp.triplePoint = pt;
1509  localTemp.intIndex.push_back(intersectionIndex);
1510  localTemp.intIndex.push_back(intersectionIndex2);
1511  tempData.push_back(localTemp);
1512  }
1513  }
1514 }
1515 
1516  // Test distances to triple points on own line of intersection
1517  // If any triple points are found to be less than 'minDist' to each other, reject.
1518  unsigned int tripSize = tempData.size();
1519  // Each tempData structure contains 1 triple pt and the intersection index of intersection it is on
1520 
1521  if (tripSize != 0 ) {
1522  unsigned int y = tripSize-1;
1523 
1524  for (unsigned int k = 0; k < y ; k++ ) {
1525  double point1[3] = {tempData[k].triplePoint.x, tempData[k].triplePoint.y, tempData[k].triplePoint.z};
1526  for (unsigned int j = k+1; j < tripSize; j++) {
1527  double point2[3] = {tempData[j].triplePoint.x, tempData[j].triplePoint.y, tempData[j].triplePoint.z};
1528  double dist = euclideanDistance(point1,point2);
1529  if ( dist < minDist && dist > eps ) {
1530 
1531  return -14;
1532  }
1533  }
1534  }
1535  }
1536  return 0;
1537 }
1538 
1539 
1540 
1541 
1542 
void translate(Poly &newPoly, double *translation)
double euclideanDistance(double *A, double *B)
bool checkDistToNewIntersections(std::vector< IntPoints > &tempIntPts, IntPoints &intPts, std::vector< TriplePtTempData > &tempTriPts, double minDistance)
struct IntPoints polyAndIntersection_RotationToXY(struct IntPoints &intersection, Poly &newPoly, std::vector< Point > &triplePoints, std::vector< Point > &tempTripPts)
unsigned int groupNum
Definition: structures.h:30
T magnitude(T x, T y, T z)
void normalize(T *vec)
int * sortedIndex(const double *v, int n)
int numberOfNodes
Definition: structures.h:14
double boundingBox[6]
Definition: structures.h:62
unsigned long long int shortIntersection
Definition: structures.h:252
unsigned long long int closeToNode
Definition: structures.h:255
unsigned long long int closeToEdge
Definition: structures.h:258
unsigned long long int triple
Definition: structures.h:264
double lineSegToLineSeg(const double *line1, const double *line2, Point &pt)
unsigned int intersectionsShortened
Definition: structures.h:344
double x2
Definition: structures.h:148
double originalLength
Definition: structures.h:347
double eps
Definition: DFNmain.cpp:39
unsigned long long int interCloseToInter
Definition: structures.h:267
void assignGroup(Poly &newPoly, Stats &pstats, int newPolyIndex)
double y2
Definition: structures.h:150
double y
Definition: structures.h:113
double y1
Definition: structures.h:144
bool parallel(double *v1, double *v2)
double z2
Definition: structures.h:152
bool pointOnLineSeg(const double *pt, const double *line)
double z1
Definition: structures.h:146
struct RejectionReasons rejectionReasons
Definition: structures.h:339
bool checkDistanceFromNodes(struct Poly &poly, IntPoints &intPts, double minDist, Stats &pstats)
bool checkBoundingBox(Poly &poly1, Poly &poly2)
void updateGroups(Poly &newPoly, std::vector< Poly > &acceptedPoly, std::vector< unsigned int > &encounteredGroups, Stats &pstats, int newPolyIndex)
int FRAM(IntPoints &intPts, unsigned int count, std::vector< IntPoints > &intPtsList, Poly &newPoly, Poly &poly2, Stats &pstats, std::vector< TriplePtTempData > &tempData, std::vector< Point > &triplePoints, std::vector< IntPoints > &tempIntPts)
Point lineIntersection3D(const double *p1, double *v1, const double *p2, double *v2)
double discardedLength
Definition: structures.h:352
bool checkCloseEdge(Poly &poly1, IntPoints &intPts, double shrinkLimit, Stats &pstats)
double x
Definition: structures.h:112
long int fract1
Definition: structures.h:135
double pointToLineSeg(const double *point, const double *line)
void applyRotation3D(Poly &newPoly, double *normalB)
int maxElmtIdx(double *v, int n)
void printBoundingBox(struct Poly &newPoly)
double * projection(const double *v1, const double *v2)
int checkForTripleIntersections(IntPoints &intPts, unsigned int count, std::vector< IntPoints > &intPtsList, Poly &newPoly, Poly &poly2, std::vector< TriplePtTempData > &tempData, std::vector< Point > &triplePoints)
double * vertices
Definition: structures.h:70
bool tripleIntersections
Definition: readInput.cpp:41
T dotProduct(const T *A, const T *B)
std::vector< unsigned int > triplePointsIdx
Definition: structures.h:154
double x1
Definition: structures.h:142
void createBoundingBox(struct Poly &newPoly)
bool checkDistToOldIntersections(std::vector< IntPoints > &intPtsList, IntPoints &intPts, Poly &poly2, double minDistance)
double z
Definition: structures.h:114
struct IntPoints findIntersections(short &flag, Poly &poly1, Poly &poly2)
std::vector< unsigned int > intersectionIndex
Definition: structures.h:98
double normal[3]
Definition: structures.h:55
double lineSegToLineSegSep(const double *line1, const double *line2)
T sqrMagnitude(T x, T y, T z)
int intersectionChecking(struct Poly &newPoly, std::vector< Poly > &acceptedPoly, std::vector< IntPoints > &intPtsList, struct Stats &pstats, std::vector< Point > &triplePoints)
bool intersectionShortened
Definition: structures.h:158
long int fract2
Definition: structures.h:139
bool shrinkIntersection(IntPoints &intPts, double *edge, double shrinkLimit, double firstNodeMinDist, double minDist)
Point lineFunction3D(double *v, double *point, double t)
double h
Definition: readInput.cpp:21
bool disableFram
Definition: readInput.cpp:30
T * crossProduct(const T *v1, const T *v2)
std::vector< int > intIndex
Definition: structures.h:186
void applyRotation2D(Poly &newPoly, float angle)
double * sumDevAry3(double *v)
double translation[3]
Definition: structures.h:52
double * rotationMatrix(double *normalA, double *normalB)