Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
PeriodicGlidePlane.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_PeriodicGlidePlane_cpp_
9#define model_PeriodicGlidePlane_cpp_
10
11#include <numbers>
12#include <memory>
13#include <math.h>
14
15#include <Polyhedron.h>
16#include <MeshBoundarySegment.h>
17#include <PeriodicGlidePlane.h>
18//#include <PeriodicGlidePlane.hpp>
20
21namespace model
22{
23
24 template<int dim>
26 const std::shared_ptr<PeriodicPlaneNode<dim>>& source_in,
27 const std::shared_ptr<PeriodicPlaneNode<dim>>& sink_in,
28 const std::shared_ptr<const MeshBoundarySegment<dim>> meshIntersection_in,
29 const short int& edgeID_in) :
30 /* init */ patch(patch_in)
31 /* init */,source(source_in)
32 /* init */,sink(sink_in)
33 /* init */,meshIntersection(meshIntersection_in)
34 /* init */,edgeID(edgeID_in)
35 // /* init */,deltaShift(getDeltaShift(patch,meshIntersection))
36 /* init */,deltaShift(meshIntersection->periodicShift())
37 /* init */,next(nullptr)
38 /* init */,prev(nullptr)
39 /* init */,twin(nullptr)
40 {
41 // std::cout<<"Creating PeriodicPlaneEdge "<<this->tag()<<std::endl;
42 source->addLink(this);
43 sink->addLink(this);
44 if(twin)
45 {
46 patch->patchBoundary->removeUntwinnedEdge(twin);
47 }
48 else
49 {
50 patch->patchBoundary->addUntwinnedEdge(this);
51 }
52 }
53
54 template<int dim>
56 {
57 // std::cout<<"Destroying PeriodicPlaneEdge "<<this->tag()<<std::endl;
58
59 source->removeLink(this);
60 sink->removeLink(this);
61 if(next)
62 {
63 next->prev=nullptr;
64 }
65 if(prev)
66 {
67 prev->next=nullptr;
68 }
69 if(twin)
70 {
71 twin->twin=nullptr;
72 patch->patchBoundary->addUntwinnedEdge(twin);
73 }
74 else
75 {
76 patch->patchBoundary->removeUntwinnedEdge(this);
77 }
78 }
79
80 // template<int dim>
81 // typename PeriodicPlaneEdge<dim>::VectorDim PeriodicPlaneEdge<dim>::getDeltaShift(const PeriodicPlanePatch<dim>* const patch,const std::shared_ptr<const MeshBoundarySegment<dim>> meshIntersection)
82 // {
83 //
84 // // VectorDim shift(VectorDim::Zero());
85 // // for(const Polyhedron<dim,dim-1>* const face : meshIntersection->faces)
86 // // {
87 // // const auto parallelFaceID(patch->glidePlane->grain.region.parallelFaces().at(face->sID));
88 // // const auto parallelFace(patch->glidePlane->grain.region.faces().at(parallelFaceID));
89 // // shift+=(parallelFace->center()-face->center()).dot(face->outNormal())*face->outNormal();
90 //
91 // // }
92 // // return shift;
93 // // std::cout<<"Starting to calculate delta shift "<<std::endl;
94 // VectorDim shift(VectorDim::Zero());
95 // for(const Polyhedron<dim,dim-1>* const face : meshIntersection->faces)
96 // {
97 // // std::cout<<"Normal corresponding to this face "<<face->sID<<face->outNormal().transpose()<<std::endl;
98 // const auto parallelFaceID(patch->glidePlane->grain.region.parallelFaces().at(face->sID));
99 // const auto parallelFace(patch->glidePlane->grain.region.faces().at(parallelFaceID));
100 // const double parallelFD(((parallelFace->center()-face->center()).dot(face->outNormal())*face->outNormal()).norm());
101 //
102 // std::vector<VectorDim> vectorofNormals;
103 //
104 //
105 // for (const auto& pface : patch->glidePlane->grain.region.parallelFaces())
106 // {
107 // if (pface.first!= face->sID && pface.second!= face->sID)
108 // {
109 // const auto otherFaceOutNormal(patch->glidePlane->grain.region.faces().at(pface.second)->outNormal());
110 // vectorofNormals.push_back(otherFaceOutNormal);
111 // // const auto shiftDirection((face->outNormal()-(face->outNormal().dot(otherFaceOutNormal)*otherFaceOutNormal)).normalized());
112 // // std::cout<<"Shift direction "<<shiftDirection.transpose()<<std::endl;
113 // // VectorDim faceShift(shiftDirection*parallelFD/face->outNormal().dot(shiftDirection));
114 // // shift+=0.5*faceShift;
115 // }
116 // }
117 // GramSchmidt::orthoNormalize(vectorofNormals);
118 // VectorDim faceShift(face->outNormal());
119 // for (const auto& normal : vectorofNormals)
120 // {
121 // faceShift-=faceShift.dot(normal)*normal;
122 // }
123 // faceShift.normalize();
124 // shift-=faceShift*parallelFD/faceShift.dot(face->outNormal());
125 // }
126 // // std::cout<<"Finished to calculate delta shift "<<shift.transpose()<<std::endl;
127 //
128 // return shift;
129 // }
130
131 template<int dim>
132 std::string PeriodicPlaneEdge<dim>::tag() const
133 {
135 return std::to_string(source->sID) + " " + std::to_string(sink->sID)+" "+std::to_string(patch->sID)+" ("+std::to_string(edgeID)+")";
136 }
137
138
139 /**********************************************************************/
140 template<int dim>
146
147 template<int dim>
149 {
150
151 if(link->sink->sID==this->sID)
152 {// edge ends at this node, so link is an inLink
153
154 // Update _patchConnectivities
155 NodalConnectivityType& patchConnectivity(patchConnectivities()[link->patch->sID]);
156 assert(patchConnectivity.inEdge==nullptr);
157 patchConnectivity.inEdge=link;
158 if(patchConnectivity.outEdge)
159 {// and outEdge of the same patch is connected to this node
160 assert(patchConnectivity.outEdge->prev==nullptr);
161 assert(link->next==nullptr);
162 patchConnectivity.outEdge->prev=link;
163 link->next=patchConnectivity.outEdge;
164 }
165
166 // Update _neighborConnectivities
167 NodalConnectivityType& neighborConnectivity(neighborConnectivities()[link->source->sID]);
168 assert(neighborConnectivity.inEdge==nullptr || neighborConnectivity.inEdge==link);
169 neighborConnectivity.inEdge=link;
170 if(neighborConnectivity.outEdge)
171 {// and outEdge of the same patch is connected to this node
172 assert(neighborConnectivity.outEdge->twin==nullptr || neighborConnectivity.outEdge->twin==link);
173 assert(link->twin==nullptr || link->twin==neighborConnectivity.outEdge);
174 neighborConnectivity.outEdge->twin=link;
175 link->twin=neighborConnectivity.outEdge;
176 }
177
178 }
179 else if(link->source->sID==this->sID)
180 {// edge starts at this node, so link is an outLink
181
182 // Update _patchConnectivities
183 NodalConnectivityType& patchConnectivity(patchConnectivities()[link->patch->sID]);
184 assert(patchConnectivity.outEdge==nullptr);
185 patchConnectivity.outEdge=link;
186 if(patchConnectivity.inEdge)
187 {
188 assert(patchConnectivity.inEdge->next==nullptr);
189 assert(link->prev==nullptr);
190 patchConnectivity.inEdge->next=link;
191 link->prev=patchConnectivity.inEdge;
192 }
193
194 // Update _neighborConnectivities
195 NodalConnectivityType& neighborConnectivity(neighborConnectivities()[link->sink->sID]);
196 assert(neighborConnectivity.outEdge==nullptr || neighborConnectivity.outEdge==link);
197 neighborConnectivity.outEdge=link;
198 if(neighborConnectivity.inEdge)
199 {// and outEdge of the same patch is connected to this node
200 assert(neighborConnectivity.inEdge->twin==nullptr || neighborConnectivity.inEdge->twin==link);
201 assert(link->twin==nullptr || link->twin==neighborConnectivity.inEdge);
202 neighborConnectivity.inEdge->twin=link;
203 link->twin=neighborConnectivity.inEdge;
204 }
205 }
206 else
207 {
208 assert(false && "CONNECTING LINK TO NON-INCIDENT NODE");
209 }
210
211 }
212
213 template<int dim>
215 {
216
217 if(link->sink->sID==this->sID)
218 {// edge ends at this node, so link is an inLink
219
220 // Update _patchConnectivities
221 auto patchIter(patchConnectivities().find(link->patch->sID));
222 assert(patchIter!=patchConnectivities().end() && "PATCH NOT FOUND IN patchConnectivities");
223 NodalConnectivityType& patchConnectivity(patchIter->second);
224 assert(patchConnectivity.inEdge==link);
225 patchConnectivity.inEdge=nullptr;
226 if(patchConnectivity.inEdge==nullptr && patchConnectivity.outEdge==nullptr)
227 {
228 patchConnectivities().erase(patchIter);
229 }
230
231 // Update _neighborConnectivities
232 auto neighborIter(neighborConnectivities().find(link->source->sID));
233 assert(neighborIter!=neighborConnectivities().end() && "NEIGHBOR NOT FOUND IN neighborConnectivity");
234 NodalConnectivityType& neighborConnectivity(neighborIter->second);
235 assert(neighborConnectivity.inEdge==link);
236 neighborConnectivity.inEdge=nullptr;
237 if(neighborConnectivity.inEdge==nullptr && neighborConnectivity.outEdge==nullptr)
238 {
239 neighborConnectivities().erase(neighborIter);
240 }
241
242 }
243 else if(link->source->sID==this->sID)
244 {// edge starts at this node, so link is an outLink
245
246 // Update _patchConnectivities
247 auto patchIter(patchConnectivities().find(link->patch->sID));
248 assert(patchIter!=patchConnectivities().end() && "PATCH NOT FOUND IN patchConnectivities");
249 NodalConnectivityType& patchConnectivity(patchIter->second);
250 assert(patchConnectivity.outEdge==link);
251 patchConnectivity.outEdge=nullptr;
252 if(patchConnectivity.inEdge==nullptr && patchConnectivity.outEdge==nullptr)
253 {
254 patchConnectivities().erase(patchIter);
255 }
256
257 // Update _neighborConnectivities
258 auto neighborIter(neighborConnectivities().find(link->sink->sID));
259 assert(neighborIter!=neighborConnectivities().end() && "NEIGHBOR NOT FOUND IN neighborConnectivity");
260 NodalConnectivityType& neighborConnectivity(neighborIter->second);
261 assert(neighborConnectivity.outEdge==link);
262 neighborConnectivity.outEdge=nullptr;
263 if(neighborConnectivity.inEdge==nullptr && neighborConnectivity.outEdge==nullptr)
264 {
265 neighborConnectivities().erase(neighborIter);
266 }
267 }
268 else
269 {
270 assert(false && "DISCONNECTING LINK FROM NON-INCIDENT NODE");
271 }
272 }
273
274 template<int dim>
276 {
277 return _patchConnectivities;
278 }
279
280 template<int dim>
285
286 template<int dim>
288 {
289 return _neighborConnectivities;
290 }
291
292 template<int dim>
297
298 template<int dim>
300 {
302 for(const auto& connectivity : neighborConnectivities())
303 {
304 if(connectivity.second.inEdge && !connectivity.second.outEdge)
305 {
306 assert(connectivity.second.inEdge->twin==nullptr);
307 temp.insert(connectivity.second.inEdge);
308 }
309 }
310 return temp;
311 }
312
313 template<int dim>
315 {
317 for(const auto& connectivity : neighborConnectivities())
318 {
319 if(connectivity.second.outEdge && !connectivity.second.inEdge)
320 {
321 assert(connectivity.second.outEdge->twin==nullptr);
322 temp.insert(connectivity.second.outEdge);
323 }
324 }
325 return temp;
326 }
327
328 /**********************************************************************/
329 template<int dim>
331 const VectorDim& shift_in) :
332 /* init */ patchBoundary(periodicPatchBoundary_in)
333 /* init */,shift(shift_in)
334 /* init */,glidePlane(patchBoundary->getGlidePlane(shift))
335 {
336 // std::cout<<cyanColor<<"Creating patch "<<this->sID<<" with shift="<<std::setprecision(15)<<std::scientific<<shift.transpose()<<defaultColor<<std::endl;
337
338 if(isRightHandedBoundary(glidePlane->meshIntersections,*patchBoundary->referencePlane))
339 {
340 addMeshIntersections(glidePlane->meshIntersections);
341 }
342 else
343 {
344 BoundingMeshSegments<dim> flippedTemp;
345 for (auto it = glidePlane->meshIntersections.rbegin(); it != glidePlane->meshIntersections.rend(); ++it)
346 {
347 flippedTemp.emplace_back(new MeshBoundarySegment<dim>((*it)->P1,(*it)->P0,(*it)->faces));
348 }
349 addMeshIntersections(flippedTemp);
350 }
351
352 patchBoundary->updateBoundaries();
353
354 }
355
356 template<int dim>
358 {
359 // std::cout<<cyanColor<<"Destroying patch "<<this->sID<<" with shift="<<std::setprecision(15)<<std::scientific<<shift.transpose()<<defaultColor<<std::endl;
360 this->clear(); // call before updateBoundaries
361 patchBoundary->updateBoundaries();
362 }
363
364 template<int dim>
366 {
367 if(bnd.size())
368 {
369 VectorDim nA(VectorDim::Zero());
370 const VectorDim P0(bnd.front()->P0);
371 for(const auto& seg : bnd)
372 {
373 nA+= 0.5*(seg->P0-P0).cross(seg->P1-seg->P0);
374 }
375 return nA.dot(plane.unitNormal)>0.0;
376 }
377 else
378 {
379 return false;
380 }
381 }
382
383 template<int dim>
385 {
386 //
387 // std::vector<std::tuple<std::shared_ptr<PeriodicPlaneNode<dim>>,std::shared_ptr<PeriodicPlaneNode<dim>>,std::shared_ptr<MeshBoundarySegment<dim>>,double>> tempEdges;
388 // for(size_t k=0;k<bms.size();++k)
389 // {// compute 2d points on PeriodicPlane, and coneect them
390 // std::shared_ptr<PeriodicPlaneNode<dim>> source(patchBoundary->getSharedNode(bms[k]->P0,shift));
391 // std::shared_ptr<PeriodicPlaneNode<dim>> sink(patchBoundary->getSharedNode(bms[k]->P1,shift));
392 // tempEdges.emplace_back(source,sink,bms[k],0.0);
393 // }
394 //
395 // VectorLowerDim C(VectorLowerDim::Zero());
396 // for(const auto& tup : tempEdges)
397 // {
398 // C+=*std::get<0>(tup);
399 // }
400 // C/=tempEdges.size(); // position of center of patch
401 //
402 // std::pair<double,size_t> minAngle(std::numbers::pi,tempEdges.size());
403 // for(size_t k=0;k<tempEdges.size();++k)
404 // {
405 // const auto x(*std::get<0>(tempEdges[k])-C);
406 // const double angle(std::fabs(atan2(x(1),x(0))));
407 // if(angle<minAngle.first)
408 // {
409 // minAngle.first=angle;
410 // minAngle.second=k;
411 // }
412 // std::get<3>(tempEdges[k])=angle;
413 // }
414 //
415 // // store edges starting from source of minimum angle
416 // for(size_t s=0;s<tempEdges.size();++s)
417 // {
418 // const short int k((minAngle.second+s)%tempEdges.size());
419 // this->emplace_back(new PeriodicPlaneEdge<dim>(this,std::get<0>(tempEdges[k]),std::get<1>(tempEdges[k]),std::get<2>(tempEdges[k]),s));
420 // }
421
422 //
423 for(size_t k=0;k<bms.size();++k)
424 {// compute 2d points on PeriodicPlane, and coneect them
425 std::shared_ptr<PeriodicPlaneNode<dim>> source(patchBoundary->getSharedNode(bms[k]->P0,shift));
426 std::shared_ptr<PeriodicPlaneNode<dim>> sink(patchBoundary->getSharedNode(bms[k]->P1,shift));
427 //this->emplace_back(new PeriodicPlaneEdge<dim>(this,source,sink,bms[k]));
428 this->emplace_back(new PeriodicPlaneEdge<dim>(this,source,sink,bms[k],k));
429 }
430 }
431
432 template<int dim>
437
438 template<int dim>
439 std::shared_ptr<PeriodicPlaneEdge<dim>> PeriodicPlanePatch<dim>::edgeOnFaces(const std::set<const Polyhedron<dim,dim-1>*>& faces) const
440 {
441 for(const auto& edge : edges())
442 {
443 if(edge->meshIntersection->faces==faces)
444 {
445 return edge;
446 }
447 }
448 return std::shared_ptr<PeriodicPlaneEdge<dim>>(nullptr);
449 }
450
451 template<int dim>
453 {
454 // const auto& outerBoundary(outerBoundaries()[0]);
455 size_t i, j, c = 0;
456 for (i = 0, j = edges().size()-1; i < edges().size(); j = i++)
457 {
458 const VectorLowerDim& Pi(*edges()[i]->source);
459 const VectorLowerDim& Pj(*edges()[j]->source);
460
461 if ( ((Pi(1)>test(1)) != (Pj(1)>test(1))) &&
462 (test(0) < (Pj(0)-Pi(0)) * (test(1)-Pi(1)) / (Pj(1)-Pi(1)) + Pi(0)
463 //+std::numeric_limits<double>::epsilon()
464 ) )
465 {
466 c = !c;
467 }
468 }
469 return c;
470 }
471
472 template<int dim>
473 PeriodicPatchBoundary<dim>::PeriodicPatchBoundary(GlidePlaneFactory<dim>& glidePlaneFactory_in, const std::shared_ptr<GlidePlane<dim>>& referencePlane_in) :
474 /* init */ glidePlaneFactory(glidePlaneFactory_in)
475 /* init */,referencePlane(referencePlane_in)
476 // /* init */,L2G(getL2G(referencePlane->unitNormal))
477 {
478
479 assert(referencePlane->meshIntersections.size()>=3);
480 }
481
482
483 template<int dim>
488
489 template<int dim>
494
495 template<int dim>
500
501 template<int dim>
506
507 template<int dim>
512
513 template<int dim>
518
519 template<int dim>
524
525 template<int dim>
527 {
528 const size_t erased(untwinnedEdges().erase(link));
529 if(erased!=1)
530 {
531 throw std::runtime_error("COULD NOT ERASE LINK FROM BOUNDARYLINKS");
532 }
533// assert(erased==1 && "COULD NOT ERASE LINK FROM BOUNDARYLINKS");
534 }
535
536 template<int dim>
541
542 template<int dim>
544 {
545 return *this;
546 }
547
548 template<int dim>
550 {
551 if(isCompact())
552 {
553 const auto& outerBoundary(outerBoundaries()[0]);
554 size_t i, j, c = 0;
555 for (i = 0, j = outerBoundary.size()-1; i < outerBoundary.size(); j = i++)
556 {
557 const VectorLowerDim& Pi(*outerBoundary[i]->source);
558 const VectorLowerDim& Pj(*outerBoundary[j]->source);
559
560 if ( ((Pi(1)>test(1)) != (Pj(1)>test(1))) &&
561 (test(0) < (Pj(0)-Pi(0)) * (test(1)-Pi(1)) / (Pj(1)-Pi(1)) + Pi(0)) )
562 {
563 c = !c;
564 }
565 }
566 return c;
567 }
568 else
569 {
570 return 0;
571 }
572 }
573
574 template<int dim>
576 {
577 return outerBoundaries().size()==1 && innerBoundaries().size()==0;
578 }
579
580 template<int dim>
582 {// TO DO: THIS SHOULD USE THE 2D POINTS
583 if(bnd.size()>=3)
584 {
585 VectorDim nA(VectorDim::Zero());
586 const VectorDim P0(bnd.front()->meshIntersection->P0-(bnd.front())->patch->shift);
587 for(const auto& seg : bnd)
588 {
589 VectorDim temp_shift=seg->patch->shift;
590 VectorDim P0_temp=seg->meshIntersection->P0-temp_shift;
591 VectorDim P1_temp=seg->meshIntersection->P1-temp_shift;
592 nA+= 0.5*(P0_temp-P0).cross(P1_temp-P0_temp);
593 }
594 return nA;
595 }
596 else
597 {
598 return VectorDim::Zero();
599 }
600 }
601
602 template<int dim>
604 {
605 return rightHandedNormal(bnd).dot(referencePlane->unitNormal);
606 }
607
608 template<int dim>
610 {
611 return rightHandedArea(bnd)>=0.0;
612 }
613
614 template<int dim>
615 std::shared_ptr<PeriodicPlaneNode<dim> > PeriodicPatchBoundary<dim>::getSharedNode(const VectorDim& pointDim,const VectorDim& shift)
616 {
617 // const VectorLowerDim point(referencePlane->localPosition(pointDim-shift));
618 return nodes().getFromKey(referencePlane->localPosition(pointDim-shift));
619 }
620
621 template<int dim>
623 {
625 temp.reserve(untwinnedCopy.size());
626 while(true)
627 {
628 temp.push_back(currentEdge);
629 const size_t erased(untwinnedCopy.erase(currentEdge));
630 if(erased!=1)
631 {
632
633 std::cout<<"Trying to erase "<<currentEdge->tag()<<std::endl;
634 std::cout<<"untwinnedCopy is"<<std::endl;
635 for(const auto& edgePtr : untwinnedCopy)
636 {
637 std::cout<<" "<<edgePtr->tag()<<std::endl;
638 }
639
640 std::ofstream pointsFile("points.txt");
641 std::cout<<"points"<<std::endl;
642 for(const auto& node : this->nodes())
643 {
644 if(!node.second.expired())
645 {
646 pointsFile<<" "<<node.second.lock()->sID<<" "<<node.first.transpose()<<std::endl;
647 std::cout<<" "<<node.second.lock()->sID<<" "<<node.first.transpose()<<std::endl;
648 }
649 }
650
651
652 // std::ofstream edgesFile("edges.txt");
653 // for(const auto& patch : patches())
654 // {
655 // for(const auto& edge : patch.second->edges())
656 // {
657 // edgesFile<<edge->tag()<<std::endl;
658 // }
659 // }
660
661 throw std::runtime_error("could not find link in untwinnedEdges 2");
662
663// assert(erased==1 && "could not find link in untwinnedEdges 2");
664 }
665 if(temp.back()->sink->sID==temp.front()->source->sID)
666 {
667 break;
668 }
669 currentEdge=currentEdge->next;
670 while(currentEdge->twin)
671 {
672 currentEdge=currentEdge->twin->next;
673 }
674
675 }
676
677 if(temp.size())
678 {// if temp is not empty a loop was closed.
679 if(this->isRightHandedBoundary(temp))
680 {// assign temp to _outerBoundaries
681 this->_outerBoundaries.push_back(temp);
682 }
683 else
684 {// assign temp to _innerBoundaries
685 this->_innerBoundaries.push_back(temp);
686
687 }
688 }
689 }
690
691 //Other version (for the case where "must start from node with only one edge in and one edge out" is not possible)
692 template<int dim>
694 {
695 // std::cout<<"Updating OuterBoundary"<<std::endl;
696 this->outerBoundaries().clear();
697 this->innerBoundaries().clear();
698 UntwinnedEdgeContainerType untwinnedCopy(this->untwinnedEdges());
699 while(untwinnedCopy.size())
700 {
701 size_t untwinnedSize(untwinnedCopy.size());
702 for(const auto& edge : untwinnedCopy)
703 {
704 if(edge->source->outEdges().size()==1 && edge->source->inEdges().size()==1) //Discuss this with Dr. Po(Yash)
705 {// must start from node with only one edge in and one edge out
706 createNewBoundary(edge,untwinnedCopy);
707 break;
708 }
709 }
710 if (untwinnedCopy.size() && untwinnedCopy.size()==untwinnedSize) //No node exists with only one edge in and one edge out
711 {
712 createNewBoundary(*untwinnedCopy.begin(),untwinnedCopy);
713
714 }
715 }
716 }
717
718 template<int dim>
719 std::shared_ptr<PeriodicPlanePatch<dim>> PeriodicPatchBoundary<dim>::getPatch(const VectorDim& shift)
720 {
721 return patches().getFromKey(shift);
722 }
723
724 template<int dim>
726 {
727 return *this;
728 }
729
730 template<int dim>
735
736 template<int dim>
741
742 template<int dim>
743 std::shared_ptr<GlidePlane<dim>> PeriodicPatchBoundary<dim>::getGlidePlane(const VectorDim& shift)
744 {
745 return glidePlaneFactory.getFromKey(getGlidePlaneKey(shift));
746 }
747
748 template<int dim>
750 const KeyType& key_in) :
751 /* init */ PeriodicPatchBoundary<dim>(pgpf->glidePlaneFactory,pgpf->glidePlaneFactory.getFromKey(key_in))
752 // /* init */ PeriodicPatchBoundary<dim>(pgpf->glidePlaneFactory.getFromKey(key_in))
753 /* init */,glidePlaneFactory(pgpf->glidePlaneFactory)
754 /* init */,periodicGlidePlaneFactory(*pgpf)
755 /* init */,referencePlane(pgpf->glidePlaneFactory.getFromKey(key_in))
756 {
757
758 }
759
760 template<int dim>
761 std::pair<typename PeriodicGlidePlane<dim>::VectorDim,bool> PeriodicGlidePlane<dim>::findPatch(const typename PeriodicGlidePlane<dim>::VectorLowerDim& P0,const VectorDim& guessShift)
762 {
763
764 PeriodicPatchBoundary<dim> patchBoundary(glidePlaneFactory,referencePlane);
765 std::vector<std::shared_ptr<PeriodicPlanePatch<dim>>> currentPatches; // keep patches alive during search
766
767
768 // Set up a starting point
769 std::shared_ptr<PeriodicPlanePatch<dim>> lastPatch(patchBoundary.getPatch(guessShift));
770 currentPatches.push_back(lastPatch); // keep patches alive durin current line segment search
771 const std::shared_ptr<GlidePlane<dim>>& centralPlane(lastPatch->glidePlane);
772 VectorLowerDim insideReferencePoint(VectorLowerDim::Zero());
773 for(const auto& seg : centralPlane->meshIntersections) // problem is here for referencePlane not cutting mesh
774 {
775 insideReferencePoint+=referencePlane->localPosition(seg->P0-lastPatch->shift);
776 }
777 insideReferencePoint/=centralPlane->meshIntersections.size();
778 if(!lastPatch->contains(insideReferencePoint))
779 {
780 throw std::runtime_error("lastPatch does not cointain insideReferencePoint");
781 }
782// assert(lastPatch->contains(insideReferencePoint));
783
784 // Find initial point
785 // const VectorLowerDim P0(polyPoints[0]);
786 while(!lastPatch->contains(P0))
787 {
788 std::set<const PeriodicPlaneEdge<dim>*> crossdEdges;
789 for(const auto& bndEdge : patchBoundary.untwinnedEdges())
790 {// loop over outer boundaries and holes
791 SegmentSegmentDistance<dim-1> ssd(P0,insideReferencePoint,*bndEdge->source,*bndEdge->sink);
792 if(ssd.dMin<FLT_EPSILON)
793 {// intersection with current boundary found
794 // std::cout<<ssd.x0.transpose()<<std::endl;
795 crossdEdges.insert(bndEdge);
796 }
797 }
798
799 switch (crossdEdges.size())
800 {
801 case 1:
802 {
803 assert(lastPatch.get()==(*crossdEdges.begin())->patch);
804 if((*crossdEdges.begin())->deltaShift.squaredNorm()<FLT_EPSILON)
805 {
806 return std::make_pair(VectorDim::Zero(),false);
807 }
808 const VectorDim newShift((*crossdEdges.begin())->deltaShift+(*crossdEdges.begin())->patch->shift);
809 lastPatch=patchBoundary.getPatch(newShift);
810 currentPatches.push_back(lastPatch); // keep patches alive durin current line segment search
811 break;
812 }
813
814 case 2:
815 {
816 assert(lastPatch.get()==(*crossdEdges.begin())->patch);
817 assert((*crossdEdges.begin())->patch==(*crossdEdges.rbegin())->patch);
818 if(((*crossdEdges.begin())->deltaShift+(*crossdEdges.rbegin())->deltaShift).squaredNorm()<FLT_EPSILON)
819 {
820 return std::make_pair(VectorDim::Zero(),false);
821 }
822 const VectorDim newShift((*crossdEdges.begin())->deltaShift+(*crossdEdges.rbegin())->deltaShift+(*crossdEdges.begin())->patch->shift);
823 lastPatch=patchBoundary.getPatch(newShift);
824 currentPatches.push_back(lastPatch); // keep patches alive durin current line segment search
825 // const auto shiftIter(usedPatches.find(newShift));
826 // if(shiftIter==usedPatches.end())
827 // {
828 // lastPatch=usedPatches.emplace(newShift,new PeriodicPlanePatch<dim>(*this,newShift)).first->second;
829 // }
830 // else
831 // {
832 // lastPatch=shiftIter->second;
833 // }
834 //
835 //
836 // usedPatches.emplace(new PeriodicPlanePatch<dim>(*this,getShift(**crossdEdges.begin())+getShift(**crossdEdges.rbegin())+(*crossdEdges.begin())->patch->shift));
837 // getPatch(getShift(**crossdEdges.begin())+getShift(**crossdEdges.rbegin())+(*crossdEdges.begin())->patch->shift);
838 break;
839 }
840
841 default:
842 {
843 std::cout<<"untwinnedEdges().size()="<<patchBoundary.untwinnedEdges().size()<<std::endl;
844 std::cout<<"crossdEdges.size()="<<crossdEdges.size()<<std::endl;
845 assert(false && "1 or 2 edges must be crossed");
846 break;
847 }
848 }
849 }
850 assert(lastPatch->contains(P0));
851 return std::make_pair(lastPatch->shift,true);
852 }
853
854 template<int dim>
856 {
857 std::cout<<"PeriodiPlane nodes:"<<std::endl;
858 for(const auto& node : this->nodes())
859 {
860 if(!node.second.expired())
861 {
862 std::cout<<node.second.lock()->sID<<" "<<node.first.transpose()<<std::endl;
863 }
864 }
865
866 }
867
868template<int dim>
869std::vector<std::shared_ptr<PeriodicPlanePatch<dim>>> PeriodicGlidePlane<dim>::filledPatches(const std::vector<VectorDim>& patchShifts)
870{/*\returns a vector of patch-shifts (including startShifts) which closes the "holes" on pgp
871 */
872 // Collect patches of the loop. We create a temporary PeriodicPatchBoundary for this, having only the patches of this loop
874 std::set<std::shared_ptr<PeriodicPlanePatch<dim>>> tempPatches;
875 for(const auto& ps : patchShifts)
876 {
877 tempPatches.insert(patchBoundary.getPatch(ps));
878 }
879 // There may be "holes" in the patches. Close them
880 while(patchBoundary.innerBoundaries().size())
881 {
882 const PeriodicPlaneEdge<dim>* const holeEdge(*patchBoundary.innerBoundaries().front().begin());
883 tempPatches.insert(patchBoundary.getPatch(holeEdge->deltaShift+holeEdge->patch->shift));
884 }
885
886 // Now grab corresponding patches from this->patchBoundary
887 std::vector<std::shared_ptr<PeriodicPlanePatch<dim>>> temp;
888 for(const auto& patch : tempPatches)
889 {
890 temp.push_back(this->getPatch(patch->shift));
891 }
892 return temp;
893}
894
895 template<int dim>
897 /* init */ glidePlaneID(0)
898 /* init */,patchBoundaryID(0)
899 /* init */,shift(VectorDim::Zero())
900 {
901
902 }
903
904 template<int dim>
906 /* init */ glidePlaneID(patch.glidePlane->sID)
907 /* init */,patchBoundaryID(patch.patchBoundary->sID)
908 /* init */,shift(patch.shift)
909 {
910
911 }
912
913 template<int dim>
915 /* init */ glidePlaneID(0)
916 /* init */,patchBoundaryID(0)
917 /* init */,shift(VectorDim::Zero())
918 {
921 for(int d=0;d<dim;++d)
922 {
923 ss>>shift(d);
924 }
925 }
926
927 template struct PeriodicPlaneEdge<3>;
928 template struct PeriodicPatchBoundary<3>;
929 template class PeriodicPlaneNode<3>;
930 template struct PeriodicPlanePatch<3>;
931 template class PeriodicGlidePlane<3>;
932 template struct PeriodicPlanePatchIO<3>;
933
934
935}
936#endif
Class template representing a straight line at the intersection of PlanarMeshFaces.
GlidePlaneFactory< dim > & glidePlaneFactory
std::pair< VectorDim, bool > findPatch(const VectorLowerDim &, const VectorDim &)
PeriodicGlidePlaneFactoryType & periodicGlidePlaneFactory
Eigen::Matrix< double, dim-1, 1 > VectorLowerDim
const std::shared_ptr< GlidePlane< dim > > referencePlane
std::vector< std::shared_ptr< PeriodicPlanePatch< dim > > > filledPatches(const std::vector< VectorDim > &patchShifts)
PeriodicGlidePlane(PeriodicGlidePlaneFactoryType *const pgpf, const KeyType &key_in)
GlidePlaneType::KeyType KeyType
PeriodicGlidePlaneFactory< dim > PeriodicGlidePlaneFactoryType
const NodalConnectivityContainerType & neighborConnectivities() const
PeriodicPlaneEdge< dim > PeriodicPlaneEdgeType
const NodalConnectivityContainerType & patchConnectivities() const
Eigen::Matrix< double, dim-1, 1 > VectorLowerDim
void removeLink(PeriodicPlaneEdgeType *const link)
InOutEdgeContainerType outEdges() const
void addLink(PeriodicPlaneEdgeType *const link)
std::map< size_t, NodalConnectivity< dim > > NodalConnectivityContainerType
PeriodicPlaneNode(PeriodicPatchBoundary< dim > *const, const VectorLowerDim &pos)
InOutEdgeContainerType inEdges() const
NodalConnectivity< dim > NodalConnectivityType
std::set< PeriodicPlaneEdgeType * > InOutEdgeContainerType
c
Definition int_R.m:15
LatticePlaneKey< dim > GlidePlaneKey
PeriodicPlaneEdgeType * outEdge
PeriodicPlaneEdgeType * inEdge
static VectorDim rightHandedNormal(const std::vector< const PeriodicPlaneEdge< dim > * > &bnd)
void createNewBoundary(const PeriodicPlaneEdge< dim > *currentEdge, UntwinnedEdgeContainerType &untwinnedCopy)
PeriodicPatchBoundary(GlidePlaneFactory< dim > &, const std::shared_ptr< GlidePlane< dim > > &referencePlane_in)
KeyConstructableWeakPtrFactory< PeriodicPatchBoundary< dim >, PeriodicPlaneNode< dim >, typename PeriodicPlaneNode< dim >::CompareType > NodeCointainerType
std::vector< const PeriodicPlaneEdge< dim > * > BoundaryContainerType
const PatchContainerType & patches() const
BoundariesContainerType & innerBoundaries()
bool isRightHandedBoundary(const std::vector< const PeriodicPlaneEdge< dim > * > &bnd)
BoundariesContainerType _outerBoundaries
std::set< const PeriodicPlaneEdge< dim > * > UntwinnedEdgeContainerType
void addUntwinnedEdge(const PeriodicPlaneEdge< dim > *link)
std::shared_ptr< GlidePlane< dim > > getGlidePlane(const VectorDim &shift)
double rightHandedArea(const std::vector< const PeriodicPlaneEdge< dim > * > &bnd)
const std::shared_ptr< GlidePlane< dim > > referencePlane
int isInsideOuterBoundary(const VectorLowerDim &test)
BoundariesContainerType _innerBoundaries
Eigen::Matrix< double, dim-1, 1 > VectorLowerDim
KeyConstructableWeakPtrFactory< PeriodicPatchBoundary< dim >, PeriodicPlanePatch< dim >, typename PeriodicPlanePatch< dim >::CompareType > PatchContainerType
std::vector< BoundaryContainerType > BoundariesContainerType
Eigen::Matrix< double, dim, 1 > VectorDim
const UntwinnedEdgeContainerType & untwinnedEdges() const
std::shared_ptr< PeriodicPlanePatch< dim > > getPatch(const VectorDim &shift)
std::shared_ptr< PeriodicPlaneNode< dim > > getSharedNode(const VectorDim &pointDim, const VectorDim &shift)
BoundariesContainerType & outerBoundaries()
GlidePlaneFactory< dim > & glidePlaneFactory
GlidePlaneKey< dim > getGlidePlaneKey(const VectorDim &shift)
void removeUntwinnedEdge(const PeriodicPlaneEdge< dim > *link)
PeriodicPlaneEdge(const PeriodicPlanePatch< dim > *const patch_in, const std::shared_ptr< PeriodicPlaneNode< dim > > &source_in, const std::shared_ptr< PeriodicPlaneNode< dim > > &sink_in, const std::shared_ptr< const MeshBoundarySegment< dim > > meshIntersection_in, const short int &)
const std::shared_ptr< const MeshBoundarySegment< dim > > meshIntersection
PeriodicPlaneEdge< dim > * next
const std::shared_ptr< PeriodicPlaneNode< dim > > sink
const std::shared_ptr< PeriodicPlaneNode< dim > > source
PeriodicPlaneEdge< dim > * twin
const PeriodicPlanePatch< dim > *const patch
PeriodicPlaneEdge< dim > * prev
std::shared_ptr< PeriodicPlaneEdge< dim > > edgeOnFaces(const std::set< const Polyhedron< dim, dim-1 > * > &faces) const
static bool isRightHandedBoundary(const BoundingMeshSegments< dim > &, const Plane< dim > &)
const PeriodicPlaneEdgeContainerType & edges() const
Eigen::Matrix< double, dim-1, 1 > VectorLowerDim
Eigen::Matrix< double, dim, 1 > VectorDim
const std::shared_ptr< GlidePlane< dim > > glidePlane
PeriodicPatchBoundary< dim > *const patchBoundary
PeriodicPlanePatch(PeriodicPatchBoundary< dim > *const, const VectorDim &)
int contains(const VectorLowerDim &test) const
void addMeshIntersections(const BoundingMeshSegments< dim > &)
std::vector< std::shared_ptr< PeriodicPlaneEdge< dim > > > PeriodicPlaneEdgeContainerType
Eigen::Matrix< double, dim, 1 > VectorDim
int end[2]
m edges
int j
newsubseg ss[0]
int k
int i
vertex temp