Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
DislocationLoop.cpp
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MoDELib is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_DislocationLoop_cpp_
9#define model_DislocationLoop_cpp_
10
11
13#include <algorithm>
14#include <DislocationLoop.h>
16#include <SutherlandHodgman.h>
18
19namespace model
20{
21 template <int dim>
23 const VectorDim& B,
24 const std::shared_ptr<GlidePlaneType>& glidePlane_in) :
25 /* init */ Loop<DislocationLoop>(net,glidePlane_in->grain.rationalLatticeDirection(B))
26 /* init */,glidePlane(glidePlane_in)
27 /* init */,periodicGlidePlane(this->network().ddBase.dislocationDynamics().periodicGlidePlaneFactory.getFromKey(glidePlane->key))
29 /* init */,grain(glidePlane->grain)
30 /* init */,loopType(this->flow().dot(glidePlane->n)==0? DislocationLoopIO<dim>::GLISSILELOOP : DislocationLoopIO<dim>::SESSILELOOP)
31 /* init */,nA(VectorDim::Zero())
32 /* init */,nAR(VectorDim::Zero())
33 /* init */,_slippedArea(0.0)
34 /* init */,_slippedAreaRate(0.0)
35 /* init */,_rightHandedUnitNormal(VectorDim::Zero())
36 /* init */,_rightHandedUnitNormal_old(VectorDim::Zero())
37 /* init */,_rightHandedNormal(new ReciprocalLatticeDirectionType(grain))
38 /* init */,_slipSystem(nullptr)
39
40 {
41 VerboseDislocationLoop(1,"Constructing DislocationLoop "<<this->tag()<<std::endl;);
42 }
43
44 template <int dim>
45 void DislocationLoop<dim>::crossSlipBranches(std::deque<CrossSlipBranch<dim>>& csNodes,const double dt) const
46 {
47 std::deque<std::deque<std::pair<const LoopLinkType*,int>>> csBranches;
48 if(this->network().crossSlipModel)
49 {
50 const auto atJunction=[this](const auto& node)
51 {
52 for(const auto* occurrence : node->networkNode->loopNodes())
53 {
54 if(occurrence->loop().get()!=this ||
55 (occurrence!=node.get() && !occurrence->isPeriodicSubdivision()))
56 {
57 return true;
58 }
59 }
60 return false;
61 };
62 std::deque<std::pair<const LoopLinkType*,int>> currentBranch; // pair<link,cross-slip slipSystem ID>
63 auto sequence=this->linkSequence();
64 // Start on a physical segment so an initial seam connector cannot
65 // be lost before currentBranch exists. This makes cyclic branch
66 // merging independent of the loop's arbitrary starting link.
67 const auto start=std::find_if(sequence.begin(),sequence.end(),[](const auto* link)
68 {
69 return link->hasNetworkLink();
70 });
71 std::rotate(sequence.begin(),start,sequence.end());
72 for(const auto& link : sequence)
73 {
74 if(link->hasNetworkLink())
75 {
76 if(this->network().crossSlipModel->isThermal() && !currentBranch.empty())
77 {
78 if(atJunction(link->source))
79 {
80 csBranches.push_back(currentBranch);
81 currentBranch.clear();
82 }
83 }
84 const auto isCSLink(this->network().crossSlipModel->isCrossSlipLink(*link->networkLink()));
85
86 if(isCSLink.first)
87 {// a cross-slip segment
88 if(currentBranch.empty())
89 {// start of new branch
90 currentBranch.emplace_back(link,isCSLink.second.second);
91 }
92 else
93 {// existing branch
94 if(currentBranch.back().second==isCSLink.second.second)
95 {
96 currentBranch.emplace_back(link,isCSLink.second.second);
97 }
98 else
99 {// close, store, and push to currentBranch,
100 csBranches.push_back(currentBranch);
101 currentBranch.clear();
102 currentBranch.emplace_back(link,isCSLink.second.second);
103 }
104 }
105 }
106 else
107 {// not a cross-slip segment
108 if(!currentBranch.empty())
109 {// close and store branch if not empty
110 csBranches.push_back(currentBranch);
111 currentBranch.clear();
112 }
113 }
114 }
115 else
116 {
117 if(!currentBranch.empty())
118 {// close and store branch if not empty
119 currentBranch.emplace_back(link,currentBranch.back().second);
120 }
121 }
122 }
123 if(!currentBranch.empty())
124 {// close and store branch if not empty
125 csBranches.push_back(currentBranch);
126 currentBranch.clear();
127 }
128
129 if(csBranches.size()>1)
130 {// Inserted two or more branches. Merge last and first branch if possible
131 if( csBranches[0].front().first->prev==csBranches.back().back().first
132 && csBranches[0].front().second==csBranches.back().back().second
133 && (!this->network().crossSlipModel->isThermal() ||
134 !atJunction(csBranches[0].front().first->source)))
135 {
136 for(typename std::deque<std::pair<const LoopLinkType*,int>>::reverse_iterator rIter = csBranches.back().rbegin();
137 rIter != csBranches.back().rend(); ++rIter)
138 {
139 csBranches[0].push_front(*rIter);
140 }
141 csBranches.pop_back();
142 }
143 }
144
145 for(const auto& branch : csBranches)
146 {
147 if(branch.size())
148 {
149 std::optional<ThermalCrossSlipEvent> event;
150 if(this->network().crossSlipModel->isThermal())
151 {
152 std::vector<const NetworkLinkType*> links;
153 for(const auto& pair : branch)
154 {
155 if(pair.first->hasNetworkLink())
156 {
157 links.push_back(pair.first->networkLink().get());
158 }
159 }
160 event=this->network().crossSlipModel->sampleBranch(links,dt>=0.0? dt : this->network().ddBase.simulationParameters.dt);
161 if(!event)
162 {
163 continue;
164 }
165 }
166 csNodes.emplace_back(std::deque<std::shared_ptr<LoopNodeType>>(),event? event->target : branch.back().second);
167 csNodes.back().thermal=event;
168 for(const auto& pair : branch)
169 {
170 if(!pair.first->source->isPeriodicSubdivision())
171 {// Keep physical endpoints; only periodic subdivisions are omitted.
172 csNodes.back().first.emplace_back(pair.first->source);
173 }
174 }
175
176 if(csNodes.back().first.size())
177 {
178 if( branch.back().first->sink!=csNodes.back().first.back()
179 && !branch.back().first->sink->isPeriodicSubdivision())
180 {
181 csNodes.back().first.emplace_back(branch.back().first->sink);
182 }
183 }
184 }
185 }
186 }
187 }
188
189 template <int dim>
191 {
192 VerboseDislocationLoop(1,"Destroying DislocationLoop "<<this->sID<<std::endl;);
193 }
194
195 template <int dim>
200
201 template <int dim>
202 std::shared_ptr<typename TypeTraits<DislocationLoop<dim>>::LoopType> DislocationLoop<dim>::clone() const
203 {
204 return std::shared_ptr<typename TypeTraits<DislocationLoop<dim>>::LoopType>(new DislocationLoop(this->p_network(),burgers(),glidePlane));
205 }
206
207 template <int dim>
208 void DislocationLoop<dim>::initFromFile(const std::string& fileName)
209 {
210 verboseDislocationLoop=TextFileParser(fileName).readScalar<int>("verboseDislocationLoop",false);
211 }
212
213 template <int dim>
215 {
216 VectorDim area=VectorDim::Zero();
217 if(!this->loopLinks().empty())
218 {
219 const VectorDim origin=(*this->loopLinks().begin())->source->get_P();
220 for(const auto* link : this->loopLinks())
221 {
222 area+=0.5*(link->source->get_P()-origin).cross(link->sink->get_P()-origin);
223 }
224 }
225 return area;
226 }
227
228 template <int dim>
230 {
232 if(area.norm()<=FLT_EPSILON)
233 {
234 return 0.0;
235 }
236 VectorDim rate=VectorDim::Zero();
237 for(const auto* link : this->loopLinks())
238 {
239 rate+=0.5*(link->source->networkNode->get_V()+link->sink->networkNode->get_V()).cross(
240 link->sink->get_P()-link->source->get_P());
241 }
242 return area.normalized().dot(rate);
243 }
244
245 template <int dim>
247 {
248 return _slippedArea;
249 }
250
251 template <int dim>
253 {
254 return _slippedAreaRate;
255 }
256
257 template <int dim>
259 {
260 return _rightHandedUnitNormal;
261 }
262
263 template <int dim>
265 {
266 return _rightHandedUnitNormal_old;
267 }
268
269 template <int dim>
271 {
272 return *_rightHandedNormal;
273 }
274
275 template <int dim>
280
281 template <int dim>
283 const VectorDim& planePoint,
284 const VectorDim& rhN,
285 const std::vector<std::pair<VectorDim,VectorDim>>& polygonSegments)
286 {
287 double temp(0.0);
288 const double posNorm((x-planePoint).norm());
289 const double dotProd((x-planePoint).dot(rhN));
290 if(std::fabs(dotProd)>FLT_EPSILON*posNorm)
291 {// x is outside the plane of the loop
292 const VectorDim s(sgn(dotProd)*rhN); // s points along +n for points above, and along -n for points below
293 for(const auto& pair : polygonSegments)
294 {
295 VectorDim e1(pair.first-x);
296 const double e1Norm(e1.norm());
297 if(e1Norm>FLT_EPSILON)
298 {
299 e1/=e1Norm;
300 VectorDim Y1(pair.second-x);
301 const double Y1norm(Y1.norm());
302 if(Y1norm>FLT_EPSILON)
303 {
304 Y1/=Y1norm;
305 VectorDim e3(e1.cross(Y1));
306 const double e3Norm(e3.norm());
307 if(e3Norm>FLT_EPSILON)
308 {// e1 and Y1 are not align. If they are the projection on the unit sphere is a point and therefore there is no contribution to solid angle
309 e3/=e3Norm; // normalize e3
310 const VectorDim e2(e3.cross(e1));
311 const double ydy(e1.dot(Y1));
312 const double w=sqrt((1.0-ydy)/(1.0+ydy));
313 const double oneA2=sqrt(1.0+DislocationFieldBase<dim>::a2);
314 const double s3(s.dot(e3));
315 const double s3A2=sqrt(std::pow(s3,2)+DislocationFieldBase<dim>::a2);
316 temp+=2.0*s3/oneA2/s3A2*atan(s3A2*w/(oneA2-s.dot(e1)-s.dot(e2)*w));
317 }
318 }
319 }
320 }
321 }
322 return temp;
323 }
324
325 template <int dim>
326 template <typename T>
328 {
329 return (val > T(0)) - (val < T(0));
330 }
331
332 template <int dim>
334 {
335 double temp(0.0);
336 if(glidePlane)
337 {
338 if(_slippedArea>FLT_EPSILON)
339 {// a right-handed normal for the loop can be determined
340 temp+=_patches.solidAngle(x);
341 }
342 }
343 else
344 {
345 const auto linkSeq(this->linkSequence());
346 assert(linkSeq.size()==4);
347
348 std::vector<std::pair<VectorDim,VectorDim>> triangle0;
349 triangle0.emplace_back(linkSeq[0]->source->get_P(),linkSeq[0]->sink->get_P());
350 triangle0.emplace_back(linkSeq[1]->source->get_P(),linkSeq[1]->sink->get_P());
351 triangle0.emplace_back(linkSeq[1]->sink->get_P(),linkSeq[0]->source->get_P());
352 const VectorDim planePoint0(triangle0[0].first);
353 VectorDim rhN0(VectorDim::Zero());
354 for(const auto& pair : triangle0)
355 {
356 rhN0+= 0.5*(pair.first-planePoint0).cross(pair.second-pair.first);
357 }
358 const double rhN0norm(rhN0.norm());
359 if(rhN0norm>FLT_EPSILON)
360 {
361 temp+=planarSolidAngle(x,planePoint0,rhN0/rhN0norm,triangle0);
362 }
363
364 std::vector<std::pair<VectorDim,VectorDim>> triangle1;
365 triangle1.emplace_back(linkSeq[2]->source->get_P(),linkSeq[2]->sink->get_P());
366 triangle1.emplace_back(linkSeq[3]->source->get_P(),linkSeq[3]->sink->get_P());
367 triangle1.emplace_back(linkSeq[3]->sink->get_P(),linkSeq[2]->source->get_P());
368 const VectorDim planePoint1(triangle1[0].first);
369 VectorDim rhN1(VectorDim::Zero());
370 for(const auto& pair : triangle1)
371 {
372 rhN1+= 0.5*(pair.first-planePoint1).cross(pair.second-pair.first);
373 }
374 const double rhN1norm(rhN1.norm());
375 if(rhN1norm>FLT_EPSILON)
376 {
377 temp+=planarSolidAngle(x,planePoint1,rhN1/rhN1norm,triangle1);
378 }
379 }
380 return temp;
381 }
382
383 template <int dim>
384 std::tuple<double,double,double,double> DislocationLoop<dim>::loopLength() const
385 {
386 double freeLength=0.0;
387 double boundaryLength=0.0;
388 double junctionLength=0.0;
389 for(const auto& link : this->loopLinks())
390 {
391 if(link->networkLink())
392 {
393 if(link->networkLink()->isBoundarySegment())
394 {
395 boundaryLength+=(link->sink->get_P()-link->source->get_P()).norm();
396 }
397 else
398 {
399 if(link->networkLink()->loopLinks().size()==1)
400 {
401 freeLength+=(link->sink->get_P()-link->source->get_P()).norm();
402 }
403 else
404 {
405 junctionLength+=(link->sink->get_P()-link->source->get_P()).norm();
406 }
407 }
408 }
409 }
410 return std::make_tuple(freeLength,junctionLength,boundaryLength,slippedArea());
411 }
412
413 template <int dim>
414 std::shared_ptr<SlipSystem> DislocationLoop<dim>::searchSlipSystem() const
415 {
416 for(const auto& ss : grain.slipSystems())
417 {
418 if(ss.second->isSameAs(this->flow(),rightHandedNormal()))
419 {
420 return ss.second;
421 }
422 }
423 return std::shared_ptr<SlipSystem>(nullptr);
424 }
425
426 template <int dim>
428 {
429 return -burgers()*nA.transpose()/this->network().ddBase.mesh.volume();
430 }
431
432 template <int dim>
434 {
435 return -burgers()*nAR.transpose()/this->network().ddBase.mesh.volume();
436 }
437
438 template <int dim>
440 {
441 return this->flow().cartesian();
442 }
443
444 template <int dim>
446 {
447 VerboseDislocationLoop(3,"DislocationLoop "<<this->tag()<<std::endl;);
448
449 const SlipSystem* const oldSlipSystem(_slipSystem.get());
450 if(glidePlane)
451 {// a glide plane exists
452 if(_slipSystem)
453 {// a current slip system exists
454 if(_slipSystem->isSameAs(this->flow(),rightHandedNormal()))
455 {// currenst slip system still valid, don't do anything
456 }
457 else
458 {// currenst slip system not valid
459 _slipSystem=searchSlipSystem();
460 }
461 }
462 else
463 {// a current slip system does not exist
464 _slipSystem=searchSlipSystem();
465 }
466 }
467 else
468 {// no glide plane
469 _slipSystem=nullptr;
470 }
471
472 if(_slipSystem.get()!=oldSlipSystem)
473 {
474 for(const auto& link : this->loopLinks())
475 {
476 if(link->networkLink())
477 {
478 link->networkLink()->updateSlipSystem();
479 }
480 }
481 }
482 if(_slipSystem)
483 {
484 VerboseDislocationLoop(3,"_slipSystem.s= "<<_slipSystem->s.cartesian().transpose()<<std::endl;);
485 VerboseDislocationLoop(3,"_slipSystem.unitNormal= "<<_slipSystem->unitNormal.transpose()<<std::endl;);
486 }
487 else
488 {
489 VerboseDislocationLoop(3,"slipSystem NOT FOUND"<<std::endl;);
490 }
491 }
492
493 template <int dim>
494 const std::shared_ptr<SlipSystem>& DislocationLoop<dim>::slipSystem() const
495 {
496 return _slipSystem;
497 }
498
499 template <int dim>
500 bool DislocationLoop<dim>::flippedInsideOut(const int& N,const double& areaThreshold) const
501 {
505
506// for(int n=0;n<N;++n)
507// {
508// const double du((1.0*n)/N);
509//
510//
511// VectorDim newAreaVector(VectorDim::Zero());
512// const VectorDim P0((*this->loopLinks().begin())->source->get_P()-du*(*this->loopLinks().begin())->source->get_deltaP());
513// for(const auto& loopLink : this->loopLinks())
514// {
515// newAreaVector+= 0.5*(loopLink->source->get_P()-du*loopLink->source->get_deltaP()-P0).cross(loopLink->sink->get_P()-du*loopLink->sink->get_deltaP()-loopLink->source->get_P()+du*loopLink->source->get_deltaP());
516// }
517// const double newArea(newAreaVector.norm());
518// if(newArea<areaThreshold && newAreaVector.dot(_rightHandedUnitNormal)>=0.0)
519// {// area fell close to zero and rightHandedNormal did not change
520//
521// CHECK THIS IMPLEMENTATION ESPECIALLY CONDITION ON THE NORMAL.
522// ALSO, CONSIDER JUNCTIONS< SO MAYBE LOOP MUST BE ISOLATED?
523//
524// return true;
525// }
526// }
527 return false;
528 }
529
530
531 template <int dim>
533 {
534 VerboseDislocationLoop(2,"DislocationLoop "<<this->sID<<" updateGeometry"<<std::endl;);
535 _rightHandedUnitNormal_old=_rightHandedUnitNormal;
536 nA.setZero();
537 // nAR.setZero();
538 if(glidePlane)
539 {// remove numerical errors by projecting along glidePlane->unitNormal
540 if(this->loopLinks().size())
541 {
542 const VectorDim P0((*this->loopLinks().begin())->source->get_P());
543 for(const auto& loopLink : this->loopLinks())
544 {
545 nA+= 0.5*(loopLink->source->get_P()-P0).cross(loopLink->sink->get_P()-loopLink->source->get_P());
546 }
547 }
548 _slippedArea=nA.norm();
549 _rightHandedUnitNormal= _slippedArea>FLT_EPSILON? (nA/_slippedArea).eval() : VectorDim::Zero();
550 const double nnDot(_rightHandedUnitNormal.dot(glidePlane->unitNormal));
551// _rightHandedNormal= nnDot>=0.0? glidePlane->n : ReciprocalLatticeDirection<dim>(glidePlane->n*(-1));
552 _rightHandedNormal.reset(nnDot>=0.0? new ReciprocalLatticeDirectionType(glidePlane->n) : new ReciprocalLatticeDirection<dim>(glidePlane->n*(-1)));
553 _rightHandedUnitNormal=rightHandedNormal().cartesian().normalized();
554 VerboseDislocationLoop(3,"_rightHandedUnitNormal= "<<_rightHandedUnitNormal.transpose()<<std::endl;);
555 }
556 else
557 {
558 if(this->loopLinks().size())
559 {
560 const VectorDim P0((*this->loopLinks().begin())->source->get_P());
561 for(const auto& loopLink : this->loopLinks())
562 {
563 nA+= 0.5*(loopLink->source->get_P()-P0).cross(loopLink->sink->get_P()-loopLink->source->get_P());
564 }
565 Plane<dim> tempPlane(P0,nA);
566 bool isPlanar(true);
567 for(const auto& loopLink : this->loopLinks())
568 {
569 isPlanar= (isPlanar && tempPlane.contains(loopLink->source->get_P()));
570 }
571 if(!isPlanar)
572 {
573 nA.setZero();
574 }
575 _slippedArea=nA.norm();
576 _rightHandedUnitNormal= _slippedArea>FLT_EPSILON? (nA/_slippedArea).eval() : VectorDim::Zero();
577// _rightHandedNormal= grain.reciprocalLatticeDirection(_rightHandedUnitNormal);
578 _rightHandedNormal.reset(new ReciprocalLatticeDirectionType(grain.reciprocalLatticeDirection(_rightHandedUnitNormal)));
579 VerboseDislocationLoop(3,"non-glide _rightHandedUnitNormal= "<<_rightHandedUnitNormal.transpose()<<std::endl;);
580 }
581 }
583
585 {
586 std::vector<VectorDim> linkShifts;
587 std::vector<VectorDim> globalNodePos;
588
589 const auto linkSeq(this->linkSequence());
590 for(const auto& link : linkSeq)
591 {// Collect patches of the loop
592 if(link->periodicPlanePatch())
593 {
594 linkShifts.push_back(link->periodicPlanePatch()->shift);
595 }
596 // Physical-boundary nodes define the trimmed contour, including
597 // its corners. Only periodic seam subdivisions may be omitted.
598 if(!link->source->isPeriodicSubdivision())
599 {
600 globalNodePos.push_back(link->source->get_P());
601 }
602 }
603 _patches.update(linkShifts,globalNodePos);
604 }
605 }
606
607 template <int dim>
609 {
610 VerboseDislocationLoop(2,"DislocationLoop "<<this->sID<<" updateRates"<<std::endl;);
611 nAR.setZero();
612 if(glidePlane)
613 {// remove numerical errors by projecting along glidePlane->unitNormal
614 if(this->loopLinks().size())
615 {
616 for(const auto& loopLink : this->loopLinks())
617 {
618 const VectorDim linkChord(loopLink->sink->get_P()-loopLink->source->get_P());
619 nAR+=0.5*(loopLink->source->networkNode->get_V()+loopLink->sink->networkNode->get_V()).cross(linkChord);
620 }
621 }
622 _slippedAreaRate=nA.dot(nAR)/_slippedArea;
623 }
624 }
625
626 template <int dim>
627 std::vector<MeshedDislocationLoop> DislocationLoop<dim>::meshed(const double& meshSize,const double& localMeshSize) const
628 {
629 std::vector<MeshedDislocationLoop> temp;
630 for(const auto& gPatch : patches().globalPatches())
631 {
632 temp.emplace_back(burgers(),*gPatch.first->glidePlane,gPatch.second,this->network(),meshSize,localMeshSize);
633 }
634 return temp;
635 }
636
637 template <int dim>
639
640 template class DislocationLoop<3>;
641
642}
643#endif
const DislocationLoopPatches< _dim > & patches() const
VectorDim currentAreaVector() const
TraitsType::ReciprocalLatticeDirectionType ReciprocalLatticeDirectionType
TraitsType::MatrixDim MatrixDim
const VectorDim & rightHandedUnitNormal() const
DislocationLoopPatches< _dim > _patches
std::shared_ptr< LoopType > clone() const
const double & slippedArea() const
const GrainType & grain
std::tuple< double, double, double, double > loopLength() const
const VectorDim & rightHandedUnitNormalOld() const
bool flippedInsideOut(const int &N, const double &areaThreshold) const
void crossSlipBranches(std::deque< CrossSlipBranch< _dim > > &csNodes, const double dt=-1.0) const
DislocationLoop(LoopNetworkType *const, const VectorDim &, const std::shared_ptr< GlidePlaneType > &glidePlane_in)
static double planarSolidAngle(const VectorDim &x, const VectorDim &planePoint, const VectorDim &rhN, const std::vector< std::pair< VectorDim, VectorDim > > &polygonSegments)
const ReciprocalLatticeDirectionType & rightHandedNormal() const
const std::shared_ptr< SlipSystem > & slipSystem() const
TraitsType::LoopType LoopType
TraitsType::VectorDim VectorDim
TraitsType::LoopNetworkType LoopNetworkType
MatrixDim averagePlasticDistortion() const
const double & slippedAreaRate() const
const std::shared_ptr< PeriodicGlidePlaneType > periodicGlidePlane
const std::shared_ptr< GlidePlaneType > glidePlane
std::vector< MeshedDislocationLoop > meshed(const double &meshSize, const double &localMeshSize) const
static int sgn(const T &val)
std::shared_ptr< SlipSystem > searchSlipSystem() const
MatrixDim averagePlasticDistortionRate() const
double solidAngle(const VectorDim &x) const
VectorDim burgers() const
static int verboseDislocationLoop
static void initFromFile(const std::string &)
LoopLinkContainerType & loopLinks()
Definition Loop.h:84
LoopLinkSequenceType linkSequence() const
Definition Loop.h:115
Loop(LoopNetworkType *const loopNetwork_in, const FlowType &f)
Definition Loop.h:61
const FlowType & flow() const
Definition Loop.h:79
Scalar readScalar(const std::string &key, const bool &verbose=false)
initial point of the source segment B
x
Definition int_R.m:12
auto eval(const std::shared_ptr< T > &t)
static double a2
Dislocation core size squared.
bool contains(const VectorDim &P0) const
Definition Plane.cpp:33
REAL w[16]
newsubseg ss[0]
vertex temp
REAL area
vertex first