OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
geometry.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 #include "mathfem.h"
36 #include "geometry.h"
37 #include "element.h"
38 #include "dofmanager.h"
39 #include "classfactory.h"
40 #include "inputrecord.h"
41 #include "dynamicinputrecord.h"
42 #include "xfem/xfemtolerances.h"
43 #include "feinterpol.h"
44 #include "xfem/tipinfo.h"
45 
46 
47 #include <fstream>
48 #include <limits>
49 
50 namespace oofem {
55 
57 { }
58 
60  mVertices(iBasicGeometry.mVertices)
61 { }
62 
64 { }
65 
66 
67 void BasicGeometry :: removeDuplicatePoints(const double &iTolSquare)
68 {
69  if(mVertices.size() > 1) {
70  for(size_t i = mVertices.size()-1; i > 0; i--) {
71 
72  if( mVertices[i].distance_square(mVertices[i-1]) < iTolSquare ) {
73  mVertices.erase( mVertices.begin()+i );
74  }
75 
76  }
77  }
78 }
79 
81 {
82  for(size_t i = 0; i < mVertices.size(); i++) {
83  mVertices[i].add(iTrans);
84  }
85 }
86 
87 
88 double BasicGeometry :: computeLineDistance(const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iQ1, const FloatArray &iQ2)
89 {
90  FloatArray u;
91  u.beDifferenceOf(iP2, iP1);
92 
93  const double LengthP = u.computeNorm();
94 
95  FloatArray v;
96  v.beDifferenceOf(iQ2, iQ1);
97  const double LengthQ = v.computeNorm();
98 
99 
100  // Regularization coefficients (to make it possible to solve when lines are parallel)
101  const double c1 = (1.0e-14)*LengthP*LengthP;
102  const double c2 = (1.0e-14)*LengthQ*LengthQ;
103 
104  const size_t minIter = 2;
105  const size_t maxIter = 5;
106  const double absTol = 1.0e-12;
107 
108  double xi = 0.0, eta = 0.0;
109 
110  FloatArray d;
111  d = iP1;
112  d.add(xi,u);
113  d.add(-1.0, iQ1);
114  d.add(-eta, v);
115 
116  FloatMatrix K(2,2), KInv;
117  FloatArray dXi;
118 
119  bool lockXi = false, lockEta = false;
120 
121  for(size_t iter = 0; iter < maxIter; iter++) {
122 
123  if(xi < 0.0) {
124  xi = 0.0;
125  lockXi = true;
126  }
127 
128  if(xi > 1.0) {
129  xi = 1.0;
130  lockXi = true;
131  }
132 
133 
134  if(eta < 0.0) {
135  eta = 0.0;
136  lockEta = true;
137  }
138 
139  if(eta > 1.0) {
140  eta = 1.0;
141  lockEta = true;
142  }
143 
144  FloatArray R = { d.dotProduct(u) + c1*xi,
145  -d.dotProduct(v) + c2*eta};
146 
147  if(lockXi) {
148  R[0] = 0.0;
149  }
150 
151  if(lockEta) {
152  R[1] = 0.0;
153  }
154 
155  const double res = R.computeNorm();
156 // printf("iter: %lu res: %e\n", iter, res);
157 
158  if(res < absTol && iter >= minIter) {
159 // printf("xi: %e eta: %e\n", xi, eta);
160  break;
161  }
162 
163  K(0,0) = -u.dotProduct(u)-c1;
164  K(0,1) = u.dotProduct(v);
165  K(1,0) = u.dotProduct(v);
166  K(1,1) = -v.dotProduct(v)-c2;
167 
168 
169  if(lockXi) {
170  K(0,0) = -1.0;
171  K(0,1) = K(1,0) = 0.0;
172  }
173 
174  if(lockEta) {
175  K(0,1) = K(1,0) = 0.0;
176  K(1,1) = -1.0;
177  }
178 
179 
180  KInv.beInverseOf(K);
181 
182  dXi.beProductOf(KInv, R);
183 
184  xi += dXi[0];
185  eta += dXi[1];
186 
187  d = iP1;
188  d.add(xi,u);
189  d.add(-1.0, iQ1);
190  d.add(-eta, v);
191  }
192 
193  if(xi < 0.0) {
194  xi = 0.0;
195  }
196 
197  if(xi > 1.0) {
198  xi = 1.0;
199  }
200 
201  if(eta < 0.0) {
202  eta = 0.0;
203  }
204 
205  if(eta > 1.0) {
206  eta = 1.0;
207  }
208 
209  d = iP1;
210  d.add(xi,u);
211  d.add(-1.0, iQ1);
212  d.add(-eta, v);
213 
214  const double dist = d.computeNorm();
215 
216  return dist;
217 }
218 
220 {
221  int ip = this->computeNumberOfIntersectionPoints(element);
222  return ( ip > 0 );
223 }
224 
225 Line :: Line(const FloatArray &iPointA, const FloatArray &iPointB) : BasicGeometry()
226 {
227  mVertices.push_back(iPointA);
228  mVertices.push_back(iPointB);
229 }
230 
232 {
233  // TODO: Is this function correct?! /ES
234  const FloatArray &pointA = mVertices [ 0 ];
235  const FloatArray &pointB = mVertices [ 1 ];
236  double a = pointA.at(2) - pointB.at(2);
237  double b = pointB.at(1) - pointA.at(1);
238  double c = pointA.at(1) * pointB.at(2) - pointB.at(1) * pointA.at(2);
239  double l = pointA.distance(pointB);
240  return ( a * point->at(1) + b * point->at(2) + c ) / l;
241 }
242 
244 {
245  answer.beDifferenceOf(mVertices [ 1 ], mVertices [ 0 ]);
246 }
247 
249 {
250  FloatArray projection;
251  this->computeProjection(projection);
252  FloatArray tmp;
253  tmp.beDifferenceOf(* point, mVertices [ 1 ]);
254  return tmp.dotProduct(projection) / projection.computeNorm();
255 }
256 
257 void Line :: computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinArcDist) const
258 {
259  PolygonLine pl;
260  pl.insertVertexBack( mVertices[0] );
261  pl.insertVertexBack( mVertices[1] );
262 
263  pl.computeTangentialSignDist(oDist, iPoint, oMinArcDist);
264 }
265 
267 {
268 
269  int numIntersec = 0;
270  const double relTol = 1.0e-3;
271  const double LineLength = giveLength();
272  const double absTol = relTol*std::max(LineLength, XfemTolerances::giveCharacteristicElementLength() );
273 
274  const int numEdges = element->giveInterpolation()->giveNumberOfEdges();
275 
276  for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) {
277  IntArray bNodes;
278  element->giveInterpolation()->boundaryGiveNodes(bNodes, edgeIndex);
279 
280  const int nsLoc = bNodes.at(1);
281  const int neLoc = bNodes.at( bNodes.giveSize() );
282 
283  FloatArray xS = *(element->giveNode(nsLoc)->giveCoordinates() );
284  xS.resizeWithValues(2);
285  FloatArray xE = *(element->giveNode(neLoc)->giveCoordinates() );
286  xE.resizeWithValues(2);
287 
288  const double dist = BasicGeometry :: computeLineDistance(xS, xE, mVertices[0], mVertices[1]);
289 
290  if(dist < absTol) {
291  numIntersec++;
292  }
293  }
294 
295  return numIntersec;
296 }
297 
298 void Line :: computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints)
299 {
300  for ( int i = 1; i <= element->giveNumberOfDofManagers(); i++ ) {
301  int n1 = i;
302  int n2 = 0;
303  if ( i < element->giveNumberOfDofManagers() ) {
304  n2 = i + 1;
305  } else {
306  n2 = 1;
307  }
308 
309  double lsn1 = computeDistanceTo( element->giveDofManager(n1)->giveCoordinates() );
310  double lsn2 = computeDistanceTo( element->giveDofManager(n2)->giveCoordinates() );
311  double lst1 = computeTangentialDistanceToEnd( element->giveDofManager(n1)->giveCoordinates() );
312  double lst2 = computeTangentialDistanceToEnd( element->giveDofManager(n2)->giveCoordinates() );
313  if ( lsn1 * lsn2 <= 0 && lst1 <= 0 && lst2 <= 0 ) {
314  double r = lsn1 / ( lsn1 - lsn2 );
315  if ( i <= element->giveNumberOfDofManagers() ) {
316  FloatArray answer(2);
317  for ( int j = 1; j <= answer.giveSize(); j++ ) {
318  answer.at(j) = ( 1 - r ) * element->giveDofManager(n1)->giveCoordinate(j)
319  + r *element->giveDofManager(n2)->giveCoordinate(j);
320  }
321 
322  oIntersectionPoints.push_back(answer);
323  }
324  }
325  }
326 }
327 
329 {
330  const FloatArray &pointA = mVertices [ 0 ];
331  const FloatArray &pointB = mVertices [ 1 ];
332  double y = pointB.at(2) - pointA.at(2);
333  double x = pointB.at(1) - pointA.at(1);
334  return atan2(y, x);
335 }
336 
338 {
339  answer.resize(2, 2);
340  double alpha = this->computeInclinationAngle();
341  answer.at(1, 1) = cos(alpha);
342  answer.at(1, 2) = sin(alpha);
343  answer.at(2, 1) = -sin(alpha);
344  answer.at(2, 2) = cos(alpha);
345 }
346 
348 {
349  FloatArray xp;
350  FloatMatrix Qt;
351  FloatArray help;
352  this->computeTransformationMatrix(Qt);
353  help.beDifferenceOf(* point, mVertices [ 1 ]);
354  xp.beProductOf(Qt, help);
355  answer.resize(2);
356  answer.at(1) = xp.computeNorm();
357  answer.at(2) = atan2( xp.at(2), xp.at(1) );
358 }
359 
361 {
362  IRResultType result; // Required by IR_GIVE_FIELD macro
363 
364  mVertices.resize(2);
367  return IRRT_OK;
368 }
369 
371 {
372  double maxX, minX, maxY, minY;
373  if ( mVertices [ 0 ].at(1) > mVertices [ 1 ].at(1) ) {
374  maxX = mVertices [ 0 ].at(1);
375  minX = mVertices [ 1 ].at(1);
376  } else {
377  minX = mVertices [ 0 ].at(1);
378  maxX = mVertices [ 1 ].at(1);
379  }
380 
381  if ( mVertices [ 0 ].at(2) > mVertices [ 1 ].at(2) ) {
382  maxY = mVertices [ 0 ].at(2);
383  minY = mVertices [ 1 ].at(2);
384  } else {
385  minY = mVertices [ 0 ].at(2);
386  maxY = mVertices [ 1 ].at(2);
387  }
388 
389  if ( point->at(1) >= minX && point->at(1) <= maxX &&
390  point->at(2) >= minY && point->at(2) <= maxY ) {
391  return true;
392  } else {
393  return false;
394  }
395 }
396 
398 { // equivalent to up
399  int count = 0;
400  for ( int i = 1; i <= bg->giveNrVertices(); i++ ) {
401  if ( this->computeDistanceTo( & ( bg->giveVertex(i) ) ) > 0.1 ) {
402  count++;
403  }
404  }
405 
406  return ( count != 0 );
407 }
408 
409 Triangle :: Triangle(const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iP3) : BasicGeometry()
410 {
411  mVertices.push_back(iP1);
412  mVertices.push_back(iP2);
413  mVertices.push_back(iP3);
414 }
415 
417 {
418  return fabs( 0.5 * ( mVertices [ 0 ].at(1) * ( mVertices [ 1 ].at(2) - mVertices [ 2 ].at(2) )
419  + mVertices [ 1 ].at(1) * ( mVertices [ 2 ].at(2) - mVertices [ 0 ].at(2) ) +
420  mVertices [ 2 ].at(1) * ( mVertices [ 0 ].at(2) - mVertices [ 1 ].at(2) ) ) );
421 }
422 
424 {
425  return 0.25 * mVertices [ 0 ].distance(mVertices [ 1 ]) *
426  mVertices [ 1 ].distance(mVertices [ 2 ]) *
427  mVertices [ 0 ].distance(mVertices [ 2 ]) / this->getArea();
428 }
429 
431 {
432  double c = mVertices [ 0 ].distance(mVertices [ 1 ]);
433  double a = mVertices [ 1 ].distance(mVertices [ 2 ]);
434  double b = mVertices [ 0 ].distance(mVertices [ 2 ]);
435 
436  // just to avoid multiple multiplication
437  double aPow = a * a;
438  double bPow = b * b;
439  double cPow = c * c;
440 
441  answer.resize(3);
442  answer.at(1) = aPow * ( -aPow + bPow + cPow );
443  answer.at(2) = bPow * ( aPow - bPow + cPow );
444  answer.at(3) = cPow * ( aPow + bPow - cPow );
445 }
446 
448 {
449  FloatArray bar;
450  this->computeBarycentrCoor(bar);
451  double sum = bar.at(1) + bar.at(2) + bar.at(3);
452  // center of the circumcircle
453  answer.resize(2);
454  for ( int i = 1; i <= answer.giveSize(); i++ ) {
455  answer.at(i) = ( bar.at(1) * mVertices [ 0 ].at(i) + bar.at(2) * mVertices [ 1 ].at(i) + bar.at(3) * mVertices [ 2 ].at(i) ) / sum;
456  }
457 }
458 
460 {
461  printf("Triangle: ");
462  for ( size_t i = 0; i < mVertices.size(); i++ ) {
463  mVertices [ i ].printYourself();
464  }
465 
466  printf("\n");
467 }
468 
470 {
471  FloatMatrix fm(3, 3);
472  for ( int i = 1; i <= 3; i++ ) {
473  for ( int j = 1; j <= 2; j++ ) {
474  fm.at(i, j) = this->giveVertex(i).at(j);
475  }
476  fm.at(i, 3) = 1.;
477  }
478 
479  if ( fm.giveDeterminant() > 0.0001 ) {
480  return true;
481  } else {
482  return false;
483  }
484 }
485 
487 {
488  std :: swap(mVertices [ 1 ], mVertices [ 2 ]);
489 }
490 
492 {
493  FloatArray P(iP);
494 
495  const double tol2 = 1.0e-18;
496 
497  // Compute triangle normal
498  FloatArray p1p2;
499  p1p2.beDifferenceOf(mVertices [ 1 ], mVertices [ 0 ]);
500 
501  FloatArray p1p3;
502  p1p3.beDifferenceOf(mVertices [ 2 ], mVertices [ 0 ]);
503 
504 
505  // Edge 1
506  FloatArray t1;
507  t1.beDifferenceOf(mVertices [ 1 ], mVertices [ 0 ]);
508  if(t1.computeSquaredNorm() < tol2) {
509  // The triangle is degenerated
510  return false;
511  }
512  else {
513  t1.normalize();
514  }
515 
516 
517  FloatArray a1;
518 
519  // Edge 2
520  FloatArray t2;
521  t2.beDifferenceOf(mVertices [ 2 ], mVertices [ 1 ]);
522  if(t2.computeSquaredNorm() < tol2) {
523  // The triangle is degenerated
524  return false;
525  }
526  else {
527  t2.normalize();
528  }
529 
530  FloatArray a2;
531 
532 
533  // Edge 3
534  FloatArray t3;
535  t3.beDifferenceOf(mVertices [ 0 ], mVertices [ 2 ]);
536  if(t3.computeSquaredNorm() < tol2) {
537  // The triangle is degenerated
538  return false;
539  }
540  else {
541  t3.normalize();
542  }
543 
544  FloatArray a3;
545 
546 
547  // Project point onto triangle plane
548  FloatArray pProj = P;
549 
550  if( p1p2.giveSize() == 2 ) {
551  // 2D
552  a1 = {-t1[1], t1[0]};
553  a2 = {-t2[1], t2[0]};
554  a3 = {-t3[1], t3[0]};
555  }
556  else {
557  // 3D
558  FloatArray N;
559 
560  N.beVectorProductOf(p1p2, p1p3);
561 
562  if(N.computeSquaredNorm() < tol2) {
563  // The triangle is degenerated
564  return false;
565  }
566  else {
567  N.normalize();
568  }
569 
570  // Compute normal distance from triangle to point
571  FloatArray p1p;
572  p1p.beDifferenceOf(P, mVertices [ 0 ]);
573  double d = p1p.dotProduct(N);
574 
575  pProj.add(-d, N);
576 
577 
578  a1.beVectorProductOf(N, t1);
579 // if(a1.computeSquaredNorm() < tol2) {
580 // // The triangle is degenerated
581 // return false;
582 // }
583 // else {
584 // a1.normalize();
585 // }
586 
587  a2.beVectorProductOf(N, t2);
588 // if(a2.computeSquaredNorm() < tol2) {
589 // // The triangle is degenerated
590 // return false;
591 // }
592 // else {
593 // a2.normalize();
594 // }
595 
596  a3.beVectorProductOf(N, t3);
597 // if(a3.computeSquaredNorm() < tol2) {
598 // // The triangle is degenerated
599 // return false;
600 // }
601 // else {
602 // a3.normalize();
603 // }
604 
605  }
606 
607 
608  // Check if the point is on the correct side of all edges
609 
610 
611  FloatArray p1pProj;
612  p1pProj.beDifferenceOf(pProj, mVertices [ 0 ]);
613  if ( p1pProj.dotProduct(a1) < 0.0 ) {
614  return false;
615  }
616 
617 
618 
619  FloatArray p2pProj;
620  p2pProj.beDifferenceOf(pProj, mVertices [ 1 ]);
621  if ( p2pProj.dotProduct(a2) < 0.0 ) {
622  return false;
623  }
624 
625  FloatArray p3pProj;
626  p3pProj.beDifferenceOf(pProj, mVertices [ 2 ]);
627  if ( p3pProj.dotProduct(a3) < 0.0 ) {
628  return false;
629  }
630 
631  return true;
632 }
633 
634 void Triangle :: refineTriangle(std::vector<Triangle> &oRefinedTri, const Triangle &iTri)
635 {
636  const FloatArray &p1 = iTri.giveVertex(1);
637  const FloatArray &p2 = iTri.giveVertex(2);
638  const FloatArray &p3 = iTri.giveVertex(3);
639 
640  // Compute edge midpoints
641  FloatArray q1, q2, q3;
642 
643  q1.beScaled(0.5, p1);
644  q1.add(0.5, p2);
645 
646  q2.beScaled(0.5, p2);
647  q2.add(0.5, p3);
648 
649  q3.beScaled(0.5, p3);
650  q3.add(0.5, p1);
651 
652  oRefinedTri.push_back( Triangle(p1, q1, q3) );
653  oRefinedTri.push_back( Triangle(q1, q2, q3) );
654  oRefinedTri.push_back( Triangle(q1, p2, q2) );
655  oRefinedTri.push_back( Triangle(q3, q2, p3) );
656 }
657 
658 Circle :: Circle(FloatArray &center, double radius) :
659  mTangSignDist(1.0)
660 {
661  mVertices.push_back(center);
662 
663  this->radius = radius;
664 }
665 
666 void Circle :: computeNormalSignDist(double &oDist, const FloatArray &iPoint) const
667 {
668  oDist = mVertices [ 0 ].distance(iPoint) - radius;
669 }
670 
671 void Circle :: giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const
672 {
673  double angle = 2.0*M_PI*iArcPos;
674 
675  oGlobalCoord.resize(2);
676  oGlobalCoord = { mVertices[0][0] + radius*cos(angle), mVertices[0][1] + radius*sin(angle) };
677 }
678 
680 {
681  IRResultType result; // Required by IR_GIVE_FIELD macro
682 
683  mVertices.resize(1);
686  return IRRT_OK;
687 }
688 
690 {
691  int count = 0;
692  for ( int i = 1; i <= element->giveNumberOfDofManagers(); i++ ) {
693  FloatArray *nodeCoor = element->giveDofManager(i)->giveCoordinates();
694  // distance from the node to the center of the circle
695  double dist = nodeCoor->distance(mVertices [ 0 ]);
696  if ( dist > this->radius ) {
697  count++;
698  }
699  }
700 
701  if ( count == 0 || count == element->giveNumberOfDofManagers() ) {
702  return false;
703  } else {
704  return true;
705  }
706 }
707 
708 
709 
710 bool
712 {
713  double dist = this->giveVertex(1).distance(point);
714  if ( dist < this->radius ) {
715  return true;
716  }
717  return false;
718 }
719 
720 
722 { // condition should maybe be that all nodes should be inside
723  for ( int i = 1; i <= element->giveNumberOfDofManagers(); i++ ) {
724  FloatArray nodeCoord = * element->giveDofManager(i)->giveCoordinates();
725  if ( isInside(nodeCoord) ) {
726  return true;
727  }
728  }
729  return false;
730 }
731 
732 
733 
734 
735 void Circle :: computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints)
736 {
737  if ( intersects(element) ) {
738  for ( int i = 1; i <= element->giveNumberOfBoundarySides(); i++ ) {
739  std :: vector< FloatArray >oneLineIntersects;
741  FloatArray a = * element->giveDofManager ( i )->giveCoordinates();
742  FloatArray b;
743  if ( i != element->giveNumberOfBoundarySides() ) {
744  b = * element->giveDofManager ( i + 1 )->giveCoordinates();
745  } else {
746  b = * element->giveDofManager ( 1 )->giveCoordinates();
747  }
748 
749  Line l(a, b);
750  computeIntersectionPoints(& l, oneLineIntersects);
751  for ( int j = 1; j <= int ( oneLineIntersects.size() ); j++ ) {
752  oIntersectionPoints.push_back(oneLineIntersects [ j - 1 ]);
753  }
754  }
755  }
756 }
757 
758 void Circle :: computeIntersectionPoints(Line *l, std :: vector< FloatArray > &oIntersectionPoints)
759 {
760  double x1 = l->giveVertex(1).at(1);
761  double y1 = l->giveVertex(1).at(2);
762  double x2 = l->giveVertex(2).at(1);
763  double y2 = l->giveVertex(2).at(2);
764  double c1 = mVertices [ 0 ].at(1);
765  double c2 = mVertices [ 0 ].at(2);
766  double distX = x2 - x1;
767  double distY = y2 - y1;
768  double a = 0., b = 0., A, B, C;
769  if ( distX != 0.0 ) {
770  a = distY / distX;
771  b = y1 - a * x1;
772  A = 1 + a * a;
773  B = 2 * ( ( -1 ) * c1 + b * a - a * c2 );
774  C = c1 * c1 + b * b - 2 * c2 * b + c2 * c2 - radius * radius;
775  } else {
776  A = 1;
777  B = ( -1 ) * 2 * c2;
778  C = x1 * x1 - 2 * x1 * c1 + c1 * c1 + c2 * c2 - radius * radius;
779  }
780 
781  double D = B * B - 4 * A * C;
782  int sz = 0;
783  if ( D < 0 ) {
784  sz = 0;
785  } else if ( D == 0 ) {
786  sz = 1;
787  } else {
788  sz = 2;
789  }
790 
791  for ( int i = 1; i <= sz; i++ ) {
792  FloatArray point(2);
793  double fn;
794  if ( i == 1 ) {
795  fn = sqrt(D);
796  } else {
797  fn = ( -1 ) * sqrt(D);
798  }
799 
800  if ( distX != 0.0 ) {
801  point.at(1) = ( ( -1 ) * B + fn ) / ( 2 * A );
802  point.at(2) = a * point.at(1) + b;
803  } else {
804  point.at(1) = x1;
805  point.at(2) = ( ( -1 ) * B + fn ) / ( 2 * A );
806  }
807 
808  if ( l->isPointInside(& point) ) {
809  oIntersectionPoints.push_back(point);
810  }
811  }
812 }
813 
814 int
816 {
817  std :: vector< FloatArray >intersecPoints;
818 
819  this->computeIntersectionPoints(element, intersecPoints);
820  return intersecPoints.size();
821 }
822 
824 {
825  int count = 0;
826  for ( int i = 1; i <= bg->giveNrVertices(); i++ ) {
827  if ( 0.9999 * bg->giveVertex(i).distance(mVertices [ 0 ]) > this->radius ) {
828  count++;
829  }
830  }
831 
832  if ( count != 0 ) {
833  return true;
834  } else {
835  return false;
836  }
837 }
838 
840 {
841  printf("Circle: radius = %e, center = ", this->radius);
842  mVertices [ 0 ].printYourself();
843  printf("\n");
844 }
845 
846 void Circle :: giveBoundingSphere(FloatArray &oCenter, double &oRadius)
847 {
848  oCenter = mVertices [ 0 ];
849  oRadius = radius;
850 }
851 
852 
854 {
855  mDebugVtk = false;
856 #ifdef __BOOST_MODULE
857  LC.x(0.0);
858  LC.y(0.0);
859 
860  UC.x(0.0);
861  UC.y(0.0);
862 #endif
863 }
864 
865 void PolygonLine :: computeNormalSignDist(double &oDist, const FloatArray &iPoint) const
866 {
867  FloatArray point = {iPoint[0], iPoint[1]};
868 
870  int numSeg = this->giveNrVertices() - 1;
871 
872  // TODO: This can probably be done in a nicer way.
873  // Ensure that we work in 2d.
874  const int dim = 2;
875 
876  for ( int segId = 1; segId <= numSeg; segId++ ) {
877  // Crack segment
878  const FloatArray &crackP1( this->giveVertex ( segId ) );
879 
880  const FloatArray &crackP2( this->giveVertex ( segId + 1 ) );
881 
882  double dist2 = 0.0;
883  if ( segId == 1 ) {
884  // Vector from start P1 to point X
885  FloatArray u = {point.at(1) - crackP1.at(1), point.at(2) - crackP1.at(2)};
886 
887  // Line tangent vector
888  FloatArray t = {crackP2.at(1) - crackP1.at(1), crackP2.at(2) - crackP1.at(2)};
889  double l2 = t.computeSquaredNorm();
890 
891  if ( l2 > 0.0 ) {
892  double l = t.normalize();
893  double s = dot(u, t);
894 
895  if ( s > l ) {
896  // X is closest to P2
897  dist2 = point.distance_square(crackP2);
898  } else {
899  double xi = s / l;
900  FloatArray q = ( 1.0 - xi ) * crackP1 + xi * crackP2;
901  dist2 = point.distance_square(q);
902  }
903  } else {
904  // If the points P1 and P2 coincide,
905  // we can compute the distance to any
906  // of these points.
907  dist2 = point.distance_square(crackP1);
908  }
909  } else if ( segId == numSeg ) {
910  // Vector from start P1 to point X
911  FloatArray u = {point.at(1) - crackP1.at(1), point.at(2) - crackP1.at(2)};
912 
913  // Line tangent vector
914  FloatArray t = {crackP2.at(1) - crackP1.at(1), crackP2.at(2) - crackP1.at(2)};
915  double l2 = t.computeSquaredNorm();
916 
917  if ( l2 > 0.0 ) {
918  double l = t.normalize();
919  double s = dot(u, t);
920 
921  if ( s < 0.0 ) {
922  // X is closest to P1
923  dist2 = point.distance_square(crackP1);
924  } else {
925  double xi = s / l;
926  FloatArray q = ( 1.0 - xi ) * crackP1 + xi * crackP2;
927  dist2 = point.distance_square(q);
928  }
929  } else {
930  // If the points P1 and P2 coincide,
931  // we can compute the distance to any
932  // of these points.
933  dist2 = point.distance_square(crackP1);
934  }
935  } else {
936  double arcPos = -1.0, dummy;
937  dist2 = point.distance_square(crackP1, crackP2, arcPos, dummy);
938  }
939 
940  if ( dist2 < oDist*oDist ) {
941  FloatArray lineToP;
942  lineToP.beDifferenceOf(point, crackP1, dim);
943 
944  FloatArray t;
945  t.beDifferenceOf(crackP2, crackP1, dim);
946 
947  FloatArray n = {-t.at(2), t.at(1)};
948 
949  oDist = sgn( lineToP.dotProduct(n) ) * sqrt(dist2);
950  }
951  }
952 }
953 
954 void PolygonLine :: computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinArcDist) const
955 {
956  FloatArray point = iPoint;
957  point.resizeWithValues(2);
958 
959  const int numSeg = this->giveNrVertices() - 1;
960 
961  double xi = 0.0, xiUnbounded = 0.0;
962 
963  if(numSeg == 0) {
964  FloatArray crackP1 = giveVertex ( 1 );
965  oDist = crackP1.distance(iPoint);
966  oMinArcDist = 0.0;
967  return;
968  }
969 
970  if(numSeg == 1) {
971  FloatArray crackP1 = giveVertex ( 1 );
972  crackP1.resizeWithValues(2);
973  FloatArray crackP2 = giveVertex ( 2 );
974  crackP2.resizeWithValues(2);
975  point.distance(crackP1, crackP2, xi, xiUnbounded);
976 
977  if( xiUnbounded < 0.0 ) {
978  oDist = xiUnbounded*crackP1.distance(crackP2);
979  oMinArcDist = 0.0;
980  return;
981  }
982 
983  if( xiUnbounded > 1.0 ) {
984  oDist = -(xiUnbounded-1.0)*crackP1.distance(crackP2);
985  oMinArcDist = 1.0;
986  return;
987  }
988 
989  const double L = computeLength();
990  double distToStart = xi*L;
991 
992  oDist = std::min(distToStart, (L - distToStart) );
993  oMinArcDist = distToStart/L;
994  return;
995  }
996 
997  bool isBeforeStart = false, isAfterEnd = false;
998  double distBeforeStart = 0.0, distAfterEnd = 0.0;
999 
1001  // Check first segment
1002  FloatArray crackP1_start = giveVertex ( 1 );
1003  crackP1_start.resizeWithValues(2);
1004  FloatArray crackP2_start = giveVertex ( 2 );
1005  crackP2_start.resizeWithValues(2);
1006  const double distSeg_start = point.distance(crackP1_start, crackP2_start, xi, xiUnbounded);
1007 
1008  if( xiUnbounded < 0.0 ) {
1009  isBeforeStart = true;
1010  distBeforeStart = xiUnbounded*crackP1_start.distance(crackP2_start);
1011  }
1012 
1013  double arcPosPassed = crackP1_start.distance(crackP2_start);
1014  double distToStart = xi*crackP1_start.distance(crackP2_start);
1015 
1016  double minGeomDist = distSeg_start;
1017 
1018 
1019 
1020 
1022  // Check interior segments
1023  for ( int segId = 2; segId <= numSeg-1; segId++ ) {
1024  FloatArray crackP1 = giveVertex ( segId );
1025  crackP1.resizeWithValues(2);
1026  FloatArray crackP2 = giveVertex ( segId+1 );
1027  crackP2.resizeWithValues(2);
1028 
1029  const double distSeg = point.distance(crackP1, crackP2, xi, xiUnbounded);
1030 
1031  if(distSeg < minGeomDist) {
1032  isBeforeStart = false;
1033  minGeomDist = distSeg;
1034  distToStart = arcPosPassed + xi*crackP1.distance(crackP2);
1035  }
1036 
1037  arcPosPassed += crackP1.distance(crackP2);
1038 
1039  }
1040 
1041 
1042 
1044  // Check last segment
1045  FloatArray crackP1_end = giveVertex ( numSeg );
1046  crackP1_end.resizeWithValues(2);
1047  FloatArray crackP2_end = giveVertex ( numSeg+1 );
1048  crackP2_end.resizeWithValues(2);
1049  const double distSeg_end = point.distance(crackP1_end, crackP2_end, xi, xiUnbounded);
1050 
1051  if(numSeg > 1) {
1052  if( xiUnbounded > 1.0 ) {
1053  arcPosPassed += xiUnbounded*crackP1_end.distance(crackP2_end);
1054  }
1055  else {
1056  arcPosPassed += xi*crackP1_end.distance(crackP2_end);
1057  }
1058  }
1059 
1060  if(distSeg_end < minGeomDist) {
1061  isBeforeStart = false;
1062 
1063  if( xiUnbounded > 1.0 ) {
1064  isAfterEnd = true;
1065  distAfterEnd = -(xiUnbounded-1.0)*crackP1_end.distance(crackP2_end);
1066  }
1067 
1068  distToStart = arcPosPassed;
1069  }
1070 
1072  // Return result
1073 
1074  if(isBeforeStart) {
1075  oDist = distBeforeStart;
1076  oMinArcDist = 0.0;
1077  return;
1078  }
1079 
1080  if(isAfterEnd) {
1081  oDist = distAfterEnd;
1082  oMinArcDist = 1.0;
1083  return;
1084  }
1085 
1086  const double L = computeLength();
1087 
1088  oDist = std::min(distToStart, (L - distToStart) );
1089  oMinArcDist = distToStart/L;
1090 }
1091 
1092 void PolygonLine :: computeLocalCoordinates(FloatArray &oLocCoord, const FloatArray &iPoint) const
1093 { }
1094 
1096 {
1097  if( mVertices.size() == 0 ) {
1098  return 0.0;
1099  }
1100 
1101  double L = 0.0;
1102 
1103  size_t numSeg = mVertices.size() - 1;
1104 
1105  if(numSeg == 0) {
1106  return 0.0;
1107  }
1108 
1109  for ( size_t i = 0; i < numSeg; i++ ) {
1110  L += mVertices [ i ].distance(mVertices [ i + 1 ]);
1111  }
1112 
1113  return L;
1114 }
1115 
1116 void PolygonLine :: giveSubPolygon(std :: vector< FloatArray > &oPoints, const double &iXiStart, const double &iXiEnd) const
1117 {
1118  double L = computeLength();
1119  double xSegStart = 0.0, xSegEnd = 0.0;
1120  double xiSegStart = 0.0, xiSegEnd = 0.0;
1121  size_t numSeg = mVertices.size() - 1;
1122  const double xiTol = 1.0e-9;
1123  if ( iXiStart < xiTol ) {
1124  // Add first point
1125  oPoints.push_back(mVertices [ 0 ]);
1126  }
1127 
1128  for ( size_t i = 0; i < numSeg; i++ ) {
1129  xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]);
1130 
1131  xiSegStart = xSegStart / L;
1132  xiSegEnd = xSegEnd / L;
1133 
1134  if ( iXiStart > xiSegStart-xiTol && iXiStart < xiSegEnd+xiTol ) {
1135  // Start point is within the segment
1136  FloatArray p;
1137  double elXi = ( iXiStart - xiSegStart ) / ( xiSegEnd - xiSegStart );
1138  p.beScaled( ( 1.0 - elXi ), mVertices [ i ] );
1139  p.add(elXi, mVertices [ i + 1 ]);
1140  oPoints.push_back(p);
1141  }
1142 
1143 
1144  if ( iXiEnd > xiSegStart && iXiEnd < xiSegEnd ) {
1145  // End point is within the segment
1146  FloatArray p;
1147  double elXi = ( iXiEnd - xiSegStart ) / ( xiSegEnd - xiSegStart );
1148  p.beScaled( ( 1.0 - elXi ), mVertices [ i ] );
1149  p.add(elXi, mVertices [ i + 1 ]);
1150  oPoints.push_back(p);
1151  }
1152 
1153  if ( xiSegEnd > iXiStart && xiSegEnd < iXiEnd + xiTol ) {
1154  // End point of the segment is within range
1155  oPoints.push_back(mVertices [ i + 1 ]);
1156  }
1157 
1158  xSegStart = xSegEnd;
1159  }
1160 }
1161 
1162 void PolygonLine :: giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const
1163 {
1164  double L = computeLength();
1165  double xSegStart = 0.0, xSegEnd = 0.0;
1166  double xiSegStart = 0.0, xiSegEnd = 0.0;
1167  size_t numSeg = mVertices.size() - 1;
1168  const double xiTol = 1.0e-9;
1169  if ( iArcPos < xiTol ) {
1170  oGlobalCoord = mVertices [ 0 ];
1171  return;
1172  }
1173 
1174  for ( size_t i = 0; i < numSeg; i++ ) {
1175  xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]);
1176 
1177  xiSegStart = xSegStart / L;
1178  xiSegEnd = xSegEnd / L;
1179 
1180  if ( iArcPos > xiSegStart-xiTol && iArcPos < xiSegEnd+xiTol ) {
1181  // Point is within the segment
1182  FloatArray p;
1183  double elXi = ( iArcPos - xiSegStart ) / ( xiSegEnd - xiSegStart );
1184  p.beScaled( ( 1.0 - elXi ), mVertices [ i ] );
1185  p.add(elXi, mVertices [ i + 1 ]);
1186  oGlobalCoord = p;
1187  return;
1188  }
1189 
1190  }
1191 }
1192 
1193 void PolygonLine :: giveNormal(FloatArray &oNormal, const double &iArcPosition) const
1194 {
1195  double L = computeLength();
1196  double xSegStart = 0.0, xSegEnd = 0.0;
1197  double xiSegStart = 0.0, xiSegEnd = 0.0;
1198  size_t numSeg = mVertices.size() - 1;
1199  const double xiTol = 1.0e-9;
1200 
1201  for ( size_t i = 0; i < numSeg; i++ ) {
1202  xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]);
1203 
1204  xiSegStart = xSegStart / L;
1205  xiSegEnd = xSegEnd / L;
1206 
1207  if ( iArcPosition > xiSegStart-xiTol && iArcPosition < xiSegEnd+xiTol ) {
1208  // The given point is within the segment
1209 
1210  const FloatArray &p1 = mVertices [ i ];
1211  const FloatArray &p2 = mVertices [ i+1 ];
1212 
1213  FloatArray t = {p2(0) - p1(0), p2(1) - p1(1)};
1214 
1215  oNormal.resize(2);
1216  oNormal(0) = -t(1);
1217  oNormal(1) = t(0);
1218  oNormal.normalize();
1219 
1220  return;
1221  }
1222 
1223  }
1224 
1225  OOFEM_ERROR("Arc position not found.")
1226 }
1227 
1228 void PolygonLine :: giveTangent(FloatArray &oTangent, const double &iArcPosition) const
1229 {
1230  double L = computeLength();
1231  double xSegStart = 0.0, xSegEnd = 0.0;
1232  double xiSegStart = 0.0, xiSegEnd = 0.0;
1233  size_t numSeg = mVertices.size() - 1;
1234  const double xiTol = 1.0e-9;
1235 
1236  for ( size_t i = 0; i < numSeg; i++ ) {
1237  xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]);
1238 
1239  xiSegStart = xSegStart / L;
1240  xiSegEnd = xSegEnd / L;
1241 
1242  if ( iArcPosition > xiSegStart-xiTol && iArcPosition < xiSegEnd+xiTol ) {
1243  // The given point is within the segment
1244 
1245  const FloatArray &p1 = mVertices [ i ];
1246  const FloatArray &p2 = mVertices [ i+1 ];
1247 
1248  oTangent = {p2(0) - p1(0), p2(1) - p1(1)};
1249 
1250  oTangent.normalize();
1251 
1252  return;
1253  }
1254 
1255  }
1256 
1257  OOFEM_ERROR("Arc position not found.")
1258 }
1259 
1261 {
1262  IRResultType result; // Required by IR_GIVE_FIELD macro
1263 
1264 
1265  FloatArray points;
1267 
1268  int numPoints = points.giveSize() / 2;
1269 
1270  for ( int i = 1; i <= numPoints; i++ ) {
1271  mVertices.push_back({points.at(2 * ( i - 1 ) + 1), points.at( 2 * ( i ) )});
1272  }
1273 
1274 
1275 #ifdef __BOOST_MODULE
1276  // Precompute bounding box to speed up calculation of intersection points.
1277  calcBoundingBox(LC, UC);
1278 #endif
1279 
1280  return IRRT_OK;
1281 }
1282 
1284 {
1285  input.setRecordKeywordField( "PolygonLine", 1 );
1286 
1287  FloatArray points;
1288  int nVert = mVertices.size();
1289  points.resize(nVert * 2);
1290 
1291  for ( int i = 0; i < nVert; i++ ) {
1292  points.at(2 * i + 1) = mVertices [ i ].at(1);
1293  points.at(2 * i + 2) = mVertices [ i ].at(2);
1294  }
1295 
1296  input.setField(points, _IFT_PolygonLine_points);
1297 }
1298 
1299 #ifdef __BOOST_MODULE
1300 bool PolygonLine :: boundingBoxIntersects(Element *element)
1301 {
1302  // Compute element bounding box
1303  bPoint2 eLC, eUC;
1304  eLC.x( element->giveNode(1)->giveCoordinate(1) );
1305  eLC.y( element->giveNode(1)->giveCoordinate(2) );
1306 
1307  eUC.x( element->giveNode(1)->giveCoordinate(1) );
1308  eUC.y( element->giveNode(1)->giveCoordinate(2) );
1309 
1310  int numNodes = element->giveNumberOfNodes();
1311  for ( int i = 2; i <= numNodes; i++ ) {
1312  eLC.x( min( eLC.x(), element->giveNode(i)->giveCoordinate(1) ) );
1313  eLC.y( min( eLC.y(), element->giveNode(i)->giveCoordinate(2) ) );
1314 
1315  eUC.x( max( eUC.x(), element->giveNode(i)->giveCoordinate(1) ) );
1316  eUC.y( max( eUC.y(), element->giveNode(i)->giveCoordinate(2) ) );
1317  }
1318 
1319  //printf("eLC: (%e, %e) eUC: (%e, %e) ", eLC.x(), eLC.y(), eUC.x(), eUC.y() );
1320  //printf(" LC: (%e, %e) UC: (%e, %e)\n", LC.x(), LC.y(), UC.x(), UC.y() );
1321 
1322 
1323  // Check if there is any chance of overlap
1324  if ( !bOverlap(eLC, eUC, LC, UC) ) {
1325  // If the bounding boxes do not overlap,
1326  // there will certainly not be any intersections
1327  return false;
1328  }
1329 
1330 
1331  return true;
1332 }
1333 #endif
1334 
1336 {
1337  printf("Warning: entering PolygonLine :: intersects(Element *element).\n");
1338 
1339 #ifdef __BOOST_MODULE
1340  if ( !boundingBoxIntersects(element) ) {
1341  return false;
1342  }
1343 
1344  double distTol = 1.0e-9;
1345 
1346  int numSeg = this->giveNrVertices() - 1;
1347 
1348 
1349  // Loop over the crack segments and test each segment for
1350  // overlap with the element
1351  for ( int segId = 1; segId <= numSeg; segId++ ) {
1352  if ( element->giveGeometryType() == EGT_triangle_1 ) {
1353  // Crack segment
1354  bPoint2 crackP1( this->giveVertex ( segId )->at(1), this->giveVertex ( segId )->at(2) );
1355  bPoint2 crackP2( this->giveVertex ( segId + 1 )->at(1), this->giveVertex ( segId + 1 )->at(2) );
1356  bSeg2 crackSeg(crackP1, crackP2);
1357 
1358 
1359  // Triangle vertices
1360  bPoint2 x1( element->giveNode ( 1 )->giveCoordinate(1), element->giveNode ( 1 )->giveCoordinate(2) );
1361  bPoint2 x2( element->giveNode ( 2 )->giveCoordinate(1), element->giveNode ( 2 )->giveCoordinate(2) );
1362  bPoint2 x3( element->giveNode ( 3 )->giveCoordinate(1), element->giveNode ( 3 )->giveCoordinate(2) );
1363 
1364  bSeg2 edge1(x1, x2);
1365  bSeg2 edge2(x2, x3);
1366  bSeg2 edge3(x3, x1);
1367 
1368  double d1 = bDist(crackSeg, edge1);
1369  if ( d1 < distTol ) {
1370  return true;
1371  }
1372 
1373  double d2 = bDist(crackSeg, edge2);
1374  if ( d2 < distTol ) {
1375  return true;
1376  }
1377 
1378  double d3 = bDist(crackSeg, edge3);
1379  if ( d3 < distTol ) {
1380  return true;
1381  }
1382  }
1383  }
1384 
1385 
1386 
1387 #endif
1388 
1389  return false;
1390 }
1391 
1392 
1394 {
1395  return false;
1396 }
1397 
1398 bool
1400 {
1401  return false;
1402 }
1403 
1404 
1405 
1406 #ifdef __BOOST_MODULE
1407 void PolygonLine :: calcBoundingBox(bPoint2 &oLC, bPoint2 &oUC)
1408 {
1409  oLC.x( vertices->at(1)->at(1) );
1410  oLC.y( vertices->at(1)->at(2) );
1411 
1412  oUC.x( vertices->at(1)->at(1) );
1413  oUC.y( vertices->at(1)->at(2) );
1414 
1415  int numPoints = vertices->giveSize();
1416  for ( int i = 2; i <= numPoints; i++ ) {
1417  oLC.x( min( oLC.x(), vertices->at(i)->at(1) ) );
1418  oLC.y( min( oLC.y(), vertices->at(i)->at(2) ) );
1419 
1420  oUC.x( max( oUC.x(), vertices->at(i)->at(1) ) );
1421  oUC.y( max( oUC.y(), vertices->at(i)->at(2) ) );
1422  }
1423 }
1424 #endif
1425 
1426 
1427 void PolygonLine :: computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints)
1428 {
1429 
1430  for ( int i = 1; i <= element->giveNumberOfBoundarySides(); i++ ) {
1431  std :: vector< FloatArray > oneLineIntersects;
1433  FloatArray xStart = * element->giveDofManager ( i )->giveCoordinates();
1434  FloatArray xEnd;
1435  if ( i != element->giveNumberOfBoundarySides() ) {
1436  xEnd = * element->giveDofManager ( i + 1 )->giveCoordinates();
1437  } else {
1438  xEnd = * element->giveDofManager ( 1 )->giveCoordinates();
1439  }
1440 
1441 
1442  computeIntersectionPoints(xStart, xEnd, oneLineIntersects);
1443 
1444  for ( FloatArray &interSect: oneLineIntersects ) {
1445  // Check that the intersection point has not already been identified.
1446  // This may happen if the crack intersects the element exactly at a node,
1447  // so that intersection is detected for both element edges in that node.
1448 
1449  // TODO: Set tolerance in a more transparent way.
1450  double distTol = 1.0e-9;
1451 
1452  bool alreadyFound = false;
1453 
1454  FloatArray pNew = interSect;
1455 
1456  for ( FloatArray &pInterSect: oIntersectionPoints ) {
1457  FloatArray pOld = pInterSect;
1458 
1459  if ( pOld.distance(pNew) < distTol ) {
1460  alreadyFound = true;
1461  break;
1462  }
1463  }
1464 
1465  if ( !alreadyFound ) {
1466  oIntersectionPoints.push_back(interSect);
1467  }
1468  }
1469 
1470 
1471  }
1472 
1473 #if 0
1474  printf("Warning: entering PolygonLine :: computeIntersectionPoints(Element *element, std::vector< FloatArray > &oIntersectionPoints).\n");
1475 #ifdef __BOOST_MODULE
1476 
1477  if ( !boundingBoxIntersects(element) ) {
1478  return;
1479  }
1480 
1481 
1482  for ( int i = 1; i <= element->giveNumberOfBoundarySides(); i++ ) {
1483  std :: vector< FloatArray >oneLineIntersects;
1485  FloatArray a = * element->giveDofManager ( i )->giveCoordinates();
1486  FloatArray b;
1487  if ( i != element->giveNumberOfBoundarySides() ) {
1488  b = * element->giveDofManager ( i + 1 )->giveCoordinates();
1489  } else {
1490  b = * element->giveDofManager ( 1 )->giveCoordinates();
1491  }
1492 
1493  Line l(a, b);
1494 
1495  computeIntersectionPoints(& l, oneLineIntersects);
1496  for ( FloatArray &interSect: oneLineIntersects ) {
1497  // Check that the intersection point has not already been identified.
1498  // This may happen if the crack intersects the element exactly at a node,
1499  // so that intersection is detected for both element edges in that node.
1500 
1501  // TODO: Set tolerance in a more transparent way.
1502  double distTol = 1.0e-9;
1503 
1504  bool alreadyFound = false;
1505 
1506  bPoint2 pNew( interSect.at(1), interSect.at(2) );
1507 
1508  for ( FloatArray &pInterSect: oIntersectionPoints ) {
1509  bPoint2 pOld( pInterSect.at(1), pInterSect.at(2) );
1510 
1511  if ( bDist(pOld, pNew) < distTol ) {
1512  alreadyFound = true;
1513  break;
1514  }
1515  }
1516 
1517  if ( !alreadyFound ) {
1518  oIntersectionPoints.push_back(interSect);
1519  }
1520  }
1521  }
1522 #endif
1523 
1524 #endif
1525 }
1526 
1527 void PolygonLine :: computeIntersectionPoints(Line *l, std :: vector< FloatArray > &oIntersectionPoints)
1528 {
1529  printf("Warning: entering PolygonLine :: computeIntersectionPoints(Line *l, std::vector< FloatArray > &oIntersectionPoints).\n");
1530 
1531 #ifdef __BOOST_MODULE
1532 
1533 
1534  int numSeg = this->giveNrVertices() - 1;
1535 
1536 
1537  // Segment
1538  bPoint2 lineP1( l->giveVertex ( 1 )->at(1), l->giveVertex ( 1 )->at(2) );
1539  bPoint2 lineP2( l->giveVertex ( 2 )->at(1), l->giveVertex ( 2 )->at(2) );
1540  bSeg2 lineSeg(lineP1, lineP2);
1541 
1542 
1543  double distTol = 1.0e-9;
1544 
1545  bool foundOverlap = false;
1546 
1547  // Loop over the crack segments and test each segment for
1548  // overlap with the element
1549  for ( int segId = 1; segId <= numSeg; segId++ ) {
1550  // Crack segment
1551  bPoint2 crackP1( this->giveVertex ( segId )->at(1), this->giveVertex ( segId )->at(2) );
1552  bPoint2 crackP2( this->giveVertex ( segId + 1 )->at(1), this->giveVertex ( segId + 1 )->at(2) );
1553  bSeg2 crackSeg(crackP1, crackP2);
1554 
1555  bPoint2 intersectionPoint(0.0, 0.0);
1556  double d = bDist(crackSeg, lineSeg, & intersectionPoint);
1557  if ( d < distTol ) {
1558  if ( !foundOverlap ) {
1559  foundOverlap = true;
1560  oIntersectionPoints.emplace_back({intersectionPoint.x(), intersectionPoint.y()});
1561  }
1562  }
1563  }
1564 
1565 #endif
1566 }
1567 
1568 void PolygonLine :: computeIntersectionPoints(const PolygonLine &iPolygonLine, std :: vector< FloatArray > &oIntersectionPoints) const
1569 {
1570  int numSeg = this->giveNrVertices() - 1;
1571  for(int segIndex = 1; segIndex <= numSeg; segIndex++) {
1572 
1573  const FloatArray &xStart = this->giveVertex(segIndex);
1574  const FloatArray &xEnd = this->giveVertex(segIndex+1);
1575 
1576  iPolygonLine.computeIntersectionPoints(xStart, xEnd, oIntersectionPoints);
1577  }
1578 }
1579 
1580 void PolygonLine :: computeIntersectionPoints(const FloatArray &iXStart, const FloatArray &iXEnd, std :: vector< FloatArray > &oIntersectionPoints) const
1581 {
1582  const double detTol = 1.0e-15;
1583 
1584  int numSeg = this->giveNrVertices() - 1;
1585  for(int segIndex = 1; segIndex <= numSeg; segIndex++) {
1586 
1587  const FloatArray &xStart = this->giveVertex(segIndex);
1588  const FloatArray &xEnd = this->giveVertex(segIndex+1);
1589 
1590  const FloatArray t1 = {xEnd(0) - xStart(0), xEnd(1) - xStart(1)};
1591  const FloatArray t2 = {iXEnd(0) - iXStart(0), iXEnd(1) - iXStart(1)};
1592 
1593  double xi1 = 0.0, xi2 = 0.0;
1594  int maxIter = 1;
1595 
1596  for(int iter = 0; iter < maxIter; iter++) {
1597  FloatArray temp = {iXStart(0) + xi2*t2(0) - xStart(0) - xi1*t1(0), iXStart(1) + xi2*t2(1) - xStart(1) - xi1*t1(1)};
1598  FloatArray res = {-t1.dotProduct(temp), t2.dotProduct(temp)};
1599 
1600  //printf("iter: %d res: %e\n", iter, res.computeNorm() );
1601 
1602  FloatMatrix K(2,2);
1603  K(0,0) = t1.dotProduct(t1);
1604  K(0,1) = -t1.dotProduct(t2);
1605  K(1,0) = -t1.dotProduct(t2);
1606  K(1,1) = t2.dotProduct(t2);
1607 
1608  double detK = K.giveDeterminant();
1609 
1610  if(detK < detTol) {
1611  return;
1612  }
1613 
1614  FloatMatrix KInv;
1615  KInv.beInverseOf(K);
1616 
1617  FloatArray dxi;
1618  dxi.beProductOf(KInv, res);
1619 
1620  xi1 -= dxi(0);
1621  xi2 -= dxi(1);
1622  }
1623 
1624 // printf("xi1: %e xi2: %e\n", xi1, xi2);
1625 
1626 
1627  if(xi1 >= 0.0 && xi1 <= 1.0 && xi2 >= 0.0 && xi2 <= 1.0) {
1628  FloatArray pos = xStart;
1629  pos.add(xi1, t1);
1630  oIntersectionPoints.push_back(pos);
1631  }
1632 
1633  }
1634 
1635 }
1636 
1637 int
1639 {
1640  std :: vector< FloatArray >intersecPoints;
1641  this->computeIntersectionPoints(element, intersecPoints);
1642  return intersecPoints.size();
1643 }
1644 
1646 {
1647  return true;
1648 }
1649 
1651 {
1652  printf("PolygonLine:\n");
1653 
1654  for(const FloatArray &x : mVertices) {
1655  x.printYourself();
1656  }
1657 
1658  printf("\n");
1659 }
1660 
1661 void PolygonLine :: printVTK(int iTStepIndex, int iLineIndex)
1662 {
1663  // Debugging function: write crack geometry to vtk.
1664 
1665  // Write crack geometry to vtk
1666  std :: string vtkFileName;
1667  vtkFileName.append("crack");
1668  char lineIdNumberString [ 100 ];
1669  sprintf(lineIdNumberString, "%d", iLineIndex);
1670  vtkFileName.append(lineIdNumberString);
1671 
1672  vtkFileName.append("Step");
1673  char stepString [ 100 ];
1674 
1675  sprintf(stepString, "%d", iTStepIndex);
1676  vtkFileName.append(stepString);
1677 
1678  vtkFileName.append(".vtk");
1679 
1680 
1681  int numPoints = this->giveNrVertices();
1682 
1683 
1684  std :: ofstream file;
1685  file.open( vtkFileName.data() );
1686 
1687  // Write header
1688  file << "# vtk DataFile Version 2.0\n";
1689  file << "Geometry of a PolygonLine\n";
1690  file << "ASCII\n";
1691 
1692  file << "DATASET UNSTRUCTURED_GRID\n";
1693 
1694 
1695  // Write points
1696  file << "POINTS " << numPoints << "double\n";
1697 
1698  for ( int i = 1; i <= numPoints; i++ ) {
1699  file << this->giveVertex(i).at(1) << " " << this->giveVertex(i).at(2) << " 0.0\n";
1700  }
1701 
1702 
1703  // Write segments
1704  int numSeg = numPoints - 1;
1705  file << "CELLS " << numSeg << " " << numSeg * 3 << "\n";
1706 
1707  int numPointsPerSeg = 2;
1708  for ( int i = 0; i < numSeg; i++ ) {
1709  file << numPointsPerSeg << " " << i << " " << i + 1 << "\n";
1710  }
1711 
1712 
1713  // Write cell types
1714  file << "CELL_TYPES " << numSeg << "\n";
1715  int vtkCellType = 3; // line segment
1716  for ( int i = 0; i < numSeg; i++ ) {
1717  file << vtkCellType << "\n";
1718  }
1719 
1720  file.close();
1721 }
1722 
1723 
1724 bool PolygonLine :: giveTips(TipInfo &oStartTipInfo, TipInfo &oEndTipInfo) const
1725 {
1726  int nVert = giveNrVertices();
1727  if ( nVert > 1 ) {
1728  // Start tip
1729  TipInfo info1;
1730  const FloatArray &p1S = ( giveVertex(1) );
1731  const FloatArray &p2S = ( giveVertex(2) );
1732 
1733  // Tip position
1734  info1.mGlobalCoord = p1S;
1735 
1736  // Tip tangent
1737  info1.mTangDir.beDifferenceOf(p1S, p2S);
1738  info1.mTangDir.normalize();
1739 
1740  // Tip normal
1741  info1.mNormalDir = {
1742  -info1.mTangDir.at(2), info1.mTangDir.at(1)
1743  };
1744 
1745  info1.mTipIndex = 0;
1746  info1.mArcPos = 0.0;
1747 
1748  oStartTipInfo = info1;
1749 
1750  // End tip
1751  TipInfo info2;
1752  const FloatArray &p1E = ( giveVertex(nVert - 1) );
1753  const FloatArray &p2E = ( giveVertex(nVert) );
1754 
1755  // Tip position
1756  info2.mGlobalCoord = p2E;
1757 
1758  // Tip tangent
1759  info2.mTangDir.beDifferenceOf(p2E, p1E);
1760  info2.mTangDir.normalize();
1761 
1762  // Tip normal
1763  info2.mNormalDir = {
1764  -info2.mTangDir.at(2), info2.mTangDir.at(1)
1765  };
1766 
1767  info2.mTipIndex = 1;
1768  info2.mArcPos = 1.0;
1769 
1770  oEndTipInfo = info2;
1771 
1772  return true;
1773  }
1774 
1775  return false;
1776 }
1777 
1778 void PolygonLine :: giveBoundingSphere(FloatArray &oCenter, double &oRadius)
1779 {
1780  int nVert = giveNrVertices();
1781  oCenter = {
1782  0.0, 0.0
1783  };
1784  oRadius = 0.0;
1785 
1786  if ( nVert > 0 ) {
1787  for ( int i = 1; i <= nVert; i++ ) {
1788  oCenter.add( giveVertex(i) );
1789  }
1790 
1791  oCenter.times( 1.0 / double( nVert ) );
1792 
1793  for ( int i = 1; i <= nVert; i++ ) {
1794  oRadius = std :: max( oRadius, oCenter.distance( giveVertex(i) ) );
1795  }
1796  }
1797 
1798 }
1799 
1800 void PolygonLine :: cropPolygon(const double &iArcPosStart, const double &iArcPosEnd)
1801 {
1802  std::vector<FloatArray> points;
1803  giveSubPolygon(points, iArcPosStart, iArcPosEnd);
1804  setVertices(points);
1805 
1806  const double tol2 = 1.0e-18;
1807  removeDuplicatePoints(tol2);
1808 
1809 }
1810 
1812 {
1813  IRResultType result; // Required by IR_GIVE_FIELD macro
1814  IntArray idList;
1815 
1816  IR_GIVE_FIELD(ir, idList, _IFT_PointSwarm_nodeID); // Macro
1817 
1818  for ( int i = 1; i <= idList.giveSize(); i++ ) {
1819  this->idList.push_back( idList.at(i) );
1820  }
1821  return IRRT_OK;
1822 }
1823 } // end namespace oofem
double giveDeterminant() const
Returns the trace (sum of diagonal components) of the receiver.
Definition: floatmatrix.C:1408
void setField(int item, InputFieldType id)
const FloatArray & giveVertex(int n) const
Definition: geometry.h:124
virtual void printYourself()
Definition: geometry.C:459
virtual void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const
Definition: geometry.C:257
void removeDuplicatePoints(const double &iTolSquare)
Definition: geometry.C:67
virtual double computeDistanceTo(const FloatArray *point)
Computes normal signed distance between this object and a point.
Definition: geometry.C:231
virtual void printYourself()
Definition: geometry.C:839
void beVectorProductOf(const FloatArray &v1, const FloatArray &v2)
Computes vector product (or cross product) of vectors given as parameters, , and stores the result in...
Definition: floatarray.C:415
static void refineTriangle(std::vector< Triangle > &oRefinedTri, const Triangle &iTri)
Split a triangle in four.
Definition: geometry.C:634
double computeTangentialDistanceToEnd(FloatArray *point)
Definition: geometry.C:248
virtual IRResultType initializeFrom(InputRecord *ir)
Computes the normal distance to the surface not to the center.
Definition: geometry.C:1811
int mTipIndex
Definition: tipinfo.h:34
void transformIntoPolar(FloatArray *point, FloatArray &answer)
Definition: geometry.C:347
#define _IFT_Circle_center
Definition: geometry.h:54
int giveNrVertices() const
Returns number of Geometry vertices.
Definition: geometry.h:144
REGISTER_Geometry(Line)
Definition: geometry.C:51
void insertVertexBack(const FloatArray &iP)
Definition: geometry.h:131
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
int max(int i, int j)
Returns bigger value form two given decimals.
Definition: mathfem.h:71
virtual void giveInputRecord(DynamicInputRecord &input)
Definition: geometry.C:1283
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1) ...
Definition: mathfem.h:91
TipInfo gathers useful information about a crack tip, like its position and tangent direction...
Definition: tipinfo.h:24
virtual bool isOutside(BasicGeometry *bg)
Definition: geometry.C:1645
virtual FloatArray * giveCoordinates()
Definition: dofmanager.h:382
virtual bool isInside(Element *element)
Definition: geometry.C:1393
void giveNormal(FloatArray &oNormal, const double &iArcPosition) const
Definition: geometry.C:1193
Abstract base class for all finite elements.
Definition: element.h:145
virtual void giveBoundingSphere(FloatArray &oCenter, double &oRadius)
Definition: geometry.C:1778
virtual double giveCoordinate(int i)
Definition: node.C:82
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
Abstract representation of Geometry.
Definition: geometry.h:81
virtual bool intersects(Element *element)
Checks whether an element is interacted, Element reference will be later replaced by Geometry...
Definition: geometry.C:1335
virtual int giveNumberOfDofManagers() const
Definition: element.h:656
virtual FEInterpolation * giveInterpolation() const
Definition: element.h:629
#define min
virtual bool isOutside(BasicGeometry *bg)
Definition: geometry.C:397
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Sets receiver to be a - b.
Definition: floatarray.C:341
virtual int giveNumberOfNodes() const
Returns number of nodes of receiver.
Definition: element.h:662
double distance(const FloatArray &x) const
Computes the distance between position represented by receiver and position given as parameter...
Definition: floatarray.C:489
double computeLength() const
Definition: geometry.C:1095
void beScaled(double s, const FloatArray &b)
Sets receiver to be .
Definition: floatarray.C:146
double mArcPos
Definition: tipinfo.h:31
#define max
#define _IFT_Line_end
Definition: geometry.h:58
#define _IFT_Line_start
Definition: geometry.h:57
virtual bool isOutside(BasicGeometry *bg)
Definition: geometry.C:823
virtual void printVTK(int iTStepIndex, int iLineIndex)
Definition: geometry.C:1661
#define M_PI
Definition: mathfem.h:52
double dotProduct(const FloatArray &x) const
Computes the dot product (or inner product) of receiver and argument.
Definition: floatarray.C:463
bool pointIsInTriangle(const FloatArray &iP) const
Checks if the projection of the the point iP onto the triangle plane is inside the triangle...
Definition: geometry.C:491
std::vector< FloatArray > mVertices
List of geometry vertices.
Definition: geometry.h:85
#define OOFEM_ERROR(...)
Definition: error.h:61
void setVertices(const std::vector< FloatArray > &iVertices)
Definition: geometry.h:126
double computeSquaredNorm() const
Computes the square of the norm.
Definition: floatarray.C:846
void changeToAnticlockwise()
Definition: geometry.C:486
void computeProjection(FloatArray &answer)
Definition: geometry.C:243
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes the Geometry from the InputRecord.
Definition: geometry.C:360
virtual void computeIntersectionPoints(Element *element, std::vector< FloatArray > &oIntersectionPoints)
Gives intersection points between this Geometry and Element.
Definition: geometry.C:298
virtual int computeNumberOfIntersectionPoints(Element *element)
Gives number of intersection points of Geometry entity with an element, Element reference will be lat...
Definition: geometry.C:815
virtual void giveBoundingSphere(FloatArray &oCenter, double &oRadius)
Definition: geometry.C:846
static double giveCharacteristicElementLength()
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Receiver becomes the result of the product of aMatrix and anArray.
Definition: floatarray.C:676
virtual void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const
Definition: geometry.C:954
#define N(p, q)
Definition: mdm.C:367
void resizeWithValues(int s, int allocChunk=0)
Checks size of receiver towards requested bounds.
Definition: floatarray.C:615
virtual void giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const
Definition: geometry.C:1162
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
double distance_square(const FloatArray &iP1, const FloatArray &iP2, double &oXi, double &oXiUnbounded) const
Definition: floatarray.C:499
virtual void giveSubPolygon(std::vector< FloatArray > &oPoints, const double &iXiStart, const double &iXiEnd) const
Definition: geometry.C:1116
virtual int computeNumberOfIntersectionPoints(Element *element)
Gives number of intersection points of Geometry entity with an element, Element reference will be lat...
Definition: geometry.h:120
#define _IFT_PointSwarm_nodeID
Definition: geometry.h:61
virtual bool giveTips(TipInfo &oStartTipInfo, TipInfo &oEndTipInfo) const
Returns start and end tip of the geometry, if applicable.
Definition: geometry.C:1724
virtual void computeLocalCoordinates(FloatArray &oLocCoord, const FloatArray &iPoint) const
Computes arc length coordinate in the range [0,1].
Definition: geometry.C:1092
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes the Geometry from the InputRecord.
Definition: geometry.C:1260
virtual int giveNumberOfBoundarySides()
Definition: element.C:1387
virtual void boundaryGiveNodes(IntArray &answer, int boundary)=0
Gives the boundary nodes for requested boundary number.
Class representing vector of real numbers.
Definition: floatarray.h:82
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
void computeBarycentrCoor(FloatArray &answer) const
Definition: geometry.C:430
#define _IFT_Circle_radius
Definition: geometry.h:53
bool isOrientedAnticlockwise()
Definition: geometry.C:469
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
virtual bool isInside(Element *element)
Definition: geometry.C:721
double computeNorm() const
Computes the norm (or length) of the vector.
Definition: floatarray.C:840
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
Class representing the general Input Record.
Definition: inputrecord.h:101
double radius
Definition: geometry.h:257
virtual int computeNumberOfIntersectionPoints(Element *element)
Gives number of intersection points of Geometry entity with an element, Element reference will be lat...
Definition: geometry.C:1638
virtual int computeNumberOfIntersectionPoints(Element *element)
Gives number of intersection points of Geometry entity with an element, Element reference will be lat...
Definition: geometry.C:266
bool isPointInside(FloatArray *point)
Definition: geometry.C:370
FloatArray mNormalDir
Definition: tipinfo.h:33
virtual bool intersects(Element *element)
Checks whether an element is interacted, Element reference will be later replaced by Geometry...
Definition: geometry.C:219
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes the Geometry from the InputRecord.
Definition: geometry.C:679
Class representing the a dynamic Input Record.
double getArea()
Definition: geometry.C:416
void times(double s)
Multiplies receiver with scalar.
Definition: floatarray.C:818
virtual int giveNumberOfEdges() const
Returns number of edges.
Definition: feinterpol.h:479
FloatArray mTangDir
Definition: tipinfo.h:32
virtual FloatArray * giveCoordinates()
Definition: node.h:114
void setRecordKeywordField(std::string keyword, int number)
int min(int i, int j)
Returns smaller value from two given decimals.
Definition: mathfem.h:59
Triangle(const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iP3)
Definition: geometry.C:409
void push_back(const double &iVal)
Add one element.
Definition: floatarray.h:118
#define _IFT_PolygonLine_points
Definition: geometry.h:65
virtual void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const
Functions for computing signed distance in normal and tangential direction.
Definition: geometry.C:865
virtual bool intersects(Element *element)
Checks whether an element is interacted, Element reference will be later replaced by Geometry...
Definition: geometry.C:689
double getRadiusOfCircumCircle()
Definition: geometry.C:423
void cropPolygon(const double &iArcPosStart, const double &iArcPosEnd)
Keep only a part of the underlying geometry, characterized by iArcPosStart and iArcPosEnd.
Definition: geometry.C:1800
int giveSize() const
Definition: intarray.h:203
void translate(const FloatArray &iTrans)
Definition: geometry.C:80
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
virtual Element_Geometry_Type giveGeometryType() const
Returns the element geometry type.
Definition: element.C:1529
FloatArray mGlobalCoord
Definition: tipinfo.h:30
virtual double giveCoordinate(int i)
Definition: dofmanager.h:380
virtual void computeIntersectionPoints(Element *element, std::vector< FloatArray > &oIntersectionPoints)
Gives intersection points between this Geometry and Element.
Definition: geometry.C:1427
BasicGeometry()
Constructor.
virtual void computeIntersectionPoints(Element *element, std::vector< FloatArray > &oIntersectionPoints)
Gives intersection points between this Geometry and Element.
Definition: geometry.C:735
the oofem namespace is to define a context or scope in which all oofem names are defined.
DofManager * giveDofManager(int i) const
Definition: element.C:514
#define IR_GIVE_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:69
static double computeLineDistance(const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iQ1, const FloatArray &iQ2)
Computes the distance between two lines.
Definition: geometry.C:88
virtual void printYourself()
Definition: geometry.C:1650
void beInverseOf(const FloatMatrix &src)
Modifies receiver to become inverse of given parameter.
Definition: floatmatrix.C:835
double normalize()
Normalizes receiver.
Definition: floatarray.C:828
Node * giveNode(int i) const
Returns reference to the i-th node of element.
Definition: element.h:610
double giveLength() const
Definition: geometry.h:218
double computeInclinationAngle()
Definition: geometry.C:328
void computeTransformationMatrix(FloatMatrix &answer)
Definition: geometry.C:337
void add(const FloatArray &src)
Adds array src to receiver.
Definition: floatarray.C:156
virtual void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const
Functions for computing signed distance in normal and tangential direction.
Definition: geometry.C:666
double dot(const FloatArray &x, const FloatArray &y)
Definition: floatarray.C:980
virtual void giveTangent(FloatArray &oTangent, const double &iArcPosition) const
Computes tangential direction at given local coordinate (arcPos)
Definition: geometry.C:1228
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631
virtual ~BasicGeometry()
Destructor.
Definition: geometry.C:63
virtual void giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const
Definition: geometry.C:671
void computeCenterOfCircumCircle(FloatArray &answer) const
Definition: geometry.C:447

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:28 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011