8#ifndef model_PeriodicGlidePlane_cpp_
9#define model_PeriodicGlidePlane_cpp_
29 const short int& edgeID_in) :
33 ,meshIntersection(meshIntersection_in)
35 ,deltaShift(meshIntersection->periodicShift())
36 ,isPeriodicEdge(deltaShift.squaredNorm()>FLT_EPSILON && periodicFacesInSameGrain(meshIntersection_in))
37 ,outNormal(patch->glidePlane->localDirection(meshIntersection->regionBoundaryNormal(patch->glidePlane->grain.grainID)).normalized())
47 patch->patchBoundary->removeUntwinnedEdge(twin);
51 patch->patchBoundary->addUntwinnedEdge(
this);
60 for(
const auto& face : meshIntersection_in->faces)
62 if(face->periodicFacePair.second)
64 temp = (
temp && face->regionIDs==face->periodicFacePair.second->regionIDs);
76 source->removeLink(
this);
77 sink->removeLink(
this);
89 patch->patchBoundary->addUntwinnedEdge(twin);
93 patch->patchBoundary->removeUntwinnedEdge(
this);
149 std::string PeriodicPlaneEdge<dim>::tag()
const
152 return std::to_string(
source->sID) +
" " + std::to_string(sink->sID)+
" "+std::to_string(patch->sID)+
" ("+std::to_string(edgeID)+
")";
162 return next->twin->nextUntwinned();
177 return prev->twin->prevUntwinned();
196 if(link->sink->sID==this->sID)
200 NodalConnectivityType& patchConnectivity(patchConnectivities()[link->patch->sID]);
201 assert(patchConnectivity.inEdge==
nullptr);
202 patchConnectivity.inEdge=link;
203 if(patchConnectivity.outEdge)
205 assert(patchConnectivity.outEdge->prev==
nullptr);
206 assert(link->next==
nullptr);
207 patchConnectivity.outEdge->prev=link;
208 link->next=patchConnectivity.outEdge;
212 NodalConnectivityType& neighborConnectivity(neighborConnectivities()[link->source->sID]);
213 assert(neighborConnectivity.inEdge==
nullptr || neighborConnectivity.inEdge==link);
214 neighborConnectivity.inEdge=link;
215 if(neighborConnectivity.outEdge)
217 assert(neighborConnectivity.outEdge->twin==
nullptr || neighborConnectivity.outEdge->twin==link);
218 assert(link->twin==
nullptr || link->twin==neighborConnectivity.outEdge);
219 neighborConnectivity.outEdge->twin=link;
220 link->twin=neighborConnectivity.outEdge;
224 else if(link->source->sID==this->sID)
228 NodalConnectivityType& patchConnectivity(patchConnectivities()[link->patch->sID]);
229 assert(patchConnectivity.outEdge==
nullptr);
230 patchConnectivity.outEdge=link;
231 if(patchConnectivity.inEdge)
233 assert(patchConnectivity.inEdge->next==
nullptr);
234 assert(link->prev==
nullptr);
235 patchConnectivity.inEdge->next=link;
236 link->prev=patchConnectivity.inEdge;
240 NodalConnectivityType& neighborConnectivity(neighborConnectivities()[link->sink->sID]);
241 assert(neighborConnectivity.outEdge==
nullptr || neighborConnectivity.outEdge==link);
242 neighborConnectivity.outEdge=link;
243 if(neighborConnectivity.inEdge)
245 assert(neighborConnectivity.inEdge->twin==
nullptr || neighborConnectivity.inEdge->twin==link);
246 assert(link->twin==
nullptr || link->twin==neighborConnectivity.inEdge);
247 neighborConnectivity.inEdge->twin=link;
248 link->twin=neighborConnectivity.inEdge;
253 assert(
false &&
"CONNECTING LINK TO NON-INCIDENT NODE");
262 if(link->sink->sID==this->sID)
266 auto patchIter(patchConnectivities().find(link->patch->sID));
267 assert(patchIter!=patchConnectivities().
end() &&
"PATCH NOT FOUND IN patchConnectivities");
268 NodalConnectivityType& patchConnectivity(patchIter->second);
269 assert(patchConnectivity.inEdge==link);
270 patchConnectivity.inEdge=
nullptr;
271 if(patchConnectivity.inEdge==
nullptr && patchConnectivity.outEdge==
nullptr)
273 patchConnectivities().erase(patchIter);
277 auto neighborIter(neighborConnectivities().find(link->source->sID));
278 assert(neighborIter!=neighborConnectivities().
end() &&
"NEIGHBOR NOT FOUND IN neighborConnectivity");
279 NodalConnectivityType& neighborConnectivity(neighborIter->second);
280 assert(neighborConnectivity.inEdge==link);
281 neighborConnectivity.inEdge=
nullptr;
282 if(neighborConnectivity.inEdge==
nullptr && neighborConnectivity.outEdge==
nullptr)
284 neighborConnectivities().erase(neighborIter);
288 else if(link->source->sID==this->sID)
292 auto patchIter(patchConnectivities().find(link->patch->sID));
293 assert(patchIter!=patchConnectivities().
end() &&
"PATCH NOT FOUND IN patchConnectivities");
294 NodalConnectivityType& patchConnectivity(patchIter->second);
295 assert(patchConnectivity.outEdge==link);
296 patchConnectivity.outEdge=
nullptr;
297 if(patchConnectivity.inEdge==
nullptr && patchConnectivity.outEdge==
nullptr)
299 patchConnectivities().erase(patchIter);
303 auto neighborIter(neighborConnectivities().find(link->sink->sID));
304 assert(neighborIter!=neighborConnectivities().
end() &&
"NEIGHBOR NOT FOUND IN neighborConnectivity");
305 NodalConnectivityType& neighborConnectivity(neighborIter->second);
306 assert(neighborConnectivity.outEdge==link);
307 neighborConnectivity.outEdge=
nullptr;
308 if(neighborConnectivity.inEdge==
nullptr && neighborConnectivity.outEdge==
nullptr)
310 neighborConnectivities().erase(neighborIter);
315 assert(
false &&
"DISCONNECTING LINK FROM NON-INCIDENT NODE");
322 return _patchConnectivities;
328 return _patchConnectivities;
334 return _neighborConnectivities;
340 return _neighborConnectivities;
346 InOutEdgeContainerType
temp;
347 for(
const auto& connectivity : neighborConnectivities())
349 if(connectivity.second.inEdge && !connectivity.second.outEdge)
351 assert(connectivity.second.inEdge->twin==
nullptr);
352 temp.insert(connectivity.second.inEdge);
361 InOutEdgeContainerType
temp;
362 for(
const auto& connectivity : neighborConnectivities())
364 if(connectivity.second.outEdge && !connectivity.second.inEdge)
366 assert(connectivity.second.outEdge->twin==
nullptr);
367 temp.insert(connectivity.second.outEdge);
376 patchBoundary(periodicPatchBoundary_in)
378 ,glidePlane(patchBoundary->getGlidePlane(
shift))
382 if(isRightHandedBoundary(glidePlane->meshIntersections,*patchBoundary->referencePlane))
384 addMeshIntersections(glidePlane->meshIntersections);
388 BoundingMeshSegments<dim> flippedTemp;
389 for (auto it = glidePlane->meshIntersections.rbegin(); it != glidePlane->meshIntersections.rend(); ++it)
391 flippedTemp.emplace_back(new MeshBoundarySegment<dim>((*it)->P1,(*it)->P0,(*it)->faces));
393 addMeshIntersections(flippedTemp);
396 patchBoundary->updateBoundaries();
401 PeriodicPlanePatch<dim>::~PeriodicPlanePatch()
405 patchBoundary->updateBoundaries();
409 bool PeriodicPlanePatch<dim>::isRightHandedBoundary(
const BoundingMeshSegments<dim>& bnd,
const Plane<dim>& plane)
415 for(
const auto& seg : bnd)
417 nA+= 0.5*(seg->P0-
P0).cross(seg->P1-seg->P0);
419 return nA.dot(
plane.unitNormal)>0.0;
428 void PeriodicPlanePatch<dim>::addMeshIntersections(
const BoundingMeshSegments<dim>& bms)
467 for(
size_t k=0;
k<bms.size();++
k)
469 std::shared_ptr<PeriodicPlaneNode<dim>>
source(patchBoundary->getSharedNode(bms[
k]->P0,shift));
470 std::shared_ptr<PeriodicPlaneNode<dim>> sink(patchBoundary->getSharedNode(bms[
k]->P1,shift));
472 this->emplace_back(
new PeriodicPlaneEdge<dim>(
this,source,sink,bms[
k],
k));
477 const typename PeriodicPlanePatch<dim>::PeriodicPlaneEdgeContainerType& PeriodicPlanePatch<dim>::edges()
const
483 std::shared_ptr<PeriodicPlaneEdge<dim>> PeriodicPlanePatch<dim>::edgeOnFaces(
const std::set<
const Polyhedron<dim,dim-1>*>& faces)
const
485 for(
const auto& edge :
edges())
487 if(edge->meshIntersection->faces==faces)
492 return std::shared_ptr<PeriodicPlaneEdge<dim>>(
nullptr);
496 int PeriodicPlanePatch<dim>::contains(
const VectorLowerDim&
test)
const
502 const VectorLowerDim& Pi(*
edges()[
i]->source);
503 const VectorLowerDim& Pj(*
edges()[
j]->source);
505 if ( ((Pi(1)>
test(1)) != (Pj(1)>
test(1))) &&
506 (
test(0) < (Pj(0)-Pi(0)) * (
test(1)-Pi(1)) / (Pj(1)-Pi(1)) + Pi(0)
517 PeriodicPatchBoundary<dim>::PeriodicPatchBoundary(GlidePlaneFactory<dim>& glidePlaneFactory_in,
const std::shared_ptr<GlidePlane<dim>>& referencePlane_in) :
518 glidePlaneFactory(glidePlaneFactory_in)
519 ,referencePlane(referencePlane_in)
523 assert(referencePlane->meshIntersections.size()>=3);
529 return _outerBoundaries;
535 return _outerBoundaries;
541 return _innerBoundaries;
547 return _innerBoundaries;
565 untwinnedEdges().insert(link);
571 const size_t erased(untwinnedEdges().erase(link));
574 throw std::runtime_error(
"COULD NOT ERASE LINK FROM BOUNDARYLINKS");
596 const auto& outerBoundary(outerBoundaries()[0]);
598 for (
i = 0,
j = outerBoundary.size()-1;
i < outerBoundary.size();
j =
i++)
600 const VectorLowerDim& Pi(*outerBoundary[
i]->source);
601 const VectorLowerDim& Pj(*outerBoundary[
j]->source);
603 if ( ((Pi(1)>
test(1)) != (Pj(1)>
test(1))) &&
604 (
test(0) < (Pj(0)-Pi(0)) * (
test(1)-Pi(1)) / (Pj(1)-Pi(1)) + Pi(0)) )
620 return outerBoundaries().size()==1 && innerBoundaries().size()==0;
629 const VectorDim P0(bnd.front()->meshIntersection->P0-(bnd.front())->patch->shift);
630 for(
const auto& seg : bnd)
633 VectorDim P0_temp=seg->meshIntersection->P0-temp_shift;
634 VectorDim P1_temp=seg->meshIntersection->P1-temp_shift;
635 nA+= 0.5*(P0_temp-
P0).cross(P1_temp-P0_temp);
641 return VectorDim::Zero();
648 return rightHandedNormal(bnd).dot(referencePlane->unitNormal);
654 return rightHandedArea(bnd)>=0.0;
661 return nodes().getFromKey(referencePlane->localPosition(pointDim-shift));
667 BoundaryContainerType
temp;
668 temp.reserve(untwinnedCopy.size());
671 temp.push_back(currentEdge);
672 const size_t erased(untwinnedCopy.erase(currentEdge));
676 std::cout<<
"Trying to erase "<<currentEdge->tag()<<std::endl;
677 std::cout<<
"untwinnedCopy is"<<std::endl;
678 for(
const auto& edgePtr : untwinnedCopy)
680 std::cout<<
" "<<edgePtr->tag()<<std::endl;
683 std::ofstream pointsFile(
"points.txt");
684 std::cout<<
"points"<<std::endl;
685 for(
const auto& node : this->nodes())
687 if(!node.second.expired())
689 pointsFile<<
" "<<node.second.lock()->sID<<
" "<<node.first.transpose()<<std::endl;
690 std::cout<<
" "<<node.second.lock()->sID<<
" "<<node.first.transpose()<<std::endl;
704 throw std::runtime_error(
"could not find link in untwinnedEdges 2");
708 if(
temp.back()->sink->sID==
temp.front()->source->sID)
712 currentEdge=currentEdge->next;
713 while(currentEdge->twin)
715 currentEdge=currentEdge->twin->next;
722 if(this->isRightHandedBoundary(
temp))
724 this->_outerBoundaries.push_back(
temp);
728 this->_innerBoundaries.push_back(
temp);
739 this->outerBoundaries().clear();
740 this->innerBoundaries().clear();
741 UntwinnedEdgeContainerType untwinnedCopy(this->untwinnedEdges());
742 while(untwinnedCopy.size())
744 size_t untwinnedSize(untwinnedCopy.size());
745 for(
const auto& edge : untwinnedCopy)
747 if(edge->source->outEdges().size()==1 && edge->source->inEdges().size()==1)
749 createNewBoundary(edge,untwinnedCopy);
753 if (untwinnedCopy.size() && untwinnedCopy.size()==untwinnedSize)
755 createNewBoundary(*untwinnedCopy.begin(),untwinnedCopy);
764 return patches().getFromKey(shift);
788 return glidePlaneFactory.getFromKey(getGlidePlaneKey(shift));
796 ,glidePlaneFactory(pgpf->glidePlaneFactory)
797 ,periodicGlidePlaneFactory(*pgpf)
798 ,referencePlane(pgpf->glidePlaneFactory.getFromKey(key_in))
808 std::vector<std::shared_ptr<PeriodicPlanePatch<dim>>> currentPatches;
812 std::shared_ptr<PeriodicPlanePatch<dim>> lastPatch(patchBoundary.getPatch(guessShift));
813 currentPatches.push_back(lastPatch);
814 const std::shared_ptr<GlidePlane<dim>>& centralPlane(lastPatch->glidePlane);
815 VectorLowerDim insideReferencePoint(VectorLowerDim::Zero());
816 for(
const auto& seg : centralPlane->meshIntersections)
818 insideReferencePoint+=referencePlane->localPosition(seg->P0-lastPatch->shift)/centralPlane->meshIntersections.size();
821 if(!lastPatch->contains(insideReferencePoint))
823 throw std::runtime_error(
"lastPatch does not cointain insideReferencePoint");
829 while(!lastPatch->contains(P0))
831 std::set<const PeriodicPlaneEdge<dim>*> crossdEdges;
832 for(
const auto& bndEdge : patchBoundary.untwinnedEdges())
835 if(ssd.dMin<FLT_EPSILON)
838 crossdEdges.insert(bndEdge);
842 switch (crossdEdges.size())
846 assert(lastPatch.get()==(*crossdEdges.begin())->patch);
847 if((*crossdEdges.begin())->deltaShift.squaredNorm()<FLT_EPSILON)
849 return std::make_pair(VectorDim::Zero(),
false);
851 const VectorDim newShift((*crossdEdges.begin())->deltaShift+(*crossdEdges.begin())->patch->shift);
852 lastPatch=patchBoundary.getPatch(newShift);
853 currentPatches.push_back(lastPatch);
859 assert(lastPatch.get()==(*crossdEdges.begin())->patch);
860 assert((*crossdEdges.begin())->patch==(*crossdEdges.rbegin())->patch);
861 if(((*crossdEdges.begin())->deltaShift+(*crossdEdges.rbegin())->deltaShift).squaredNorm()<FLT_EPSILON)
863 return std::make_pair(VectorDim::Zero(),
false);
865 const VectorDim newShift((*crossdEdges.begin())->deltaShift+(*crossdEdges.rbegin())->deltaShift+(*crossdEdges.begin())->patch->shift);
866 lastPatch=patchBoundary.getPatch(newShift);
867 currentPatches.push_back(lastPatch);
886 std::cout<<
"untwinnedEdges().size()="<<patchBoundary.untwinnedEdges().size()<<std::endl;
887 std::cout<<
"crossdEdges.size()="<<crossdEdges.size()<<std::endl;
888 throw std::runtime_error(
"1 or 2 edges must be crossed");
894 assert(lastPatch->contains(P0));
895 if(!lastPatch->contains(P0))
897 throw std::runtime_error(
"lastPatch does not cointain searched point.");
899 return std::make_pair(lastPatch->shift,
true);
905 std::cout<<
"PeriodiPlane nodes:"<<std::endl;
906 for(
const auto& node : this->nodes())
908 if(!node.second.expired())
910 std::cout<<node.second.lock()->sID<<
" "<<node.first.transpose()<<std::endl;
922 std::set<std::shared_ptr<PeriodicPlanePatch<dim>>> tempPatches;
923 for(
const auto& ps : patchShifts)
925 tempPatches.insert(patchBoundary.getPatch(ps));
928 while(patchBoundary.innerBoundaries().size())
931 tempPatches.insert(patchBoundary.getPatch(holeEdge->deltaShift+holeEdge->patch->shift));
935 std::vector<std::shared_ptr<PeriodicPlanePatch<dim>>>
temp;
936 for(
const auto& patch : tempPatches)
938 temp.push_back(this->getPatch(patch->shift));
954 glidePlaneID(patch.glidePlane->sID)
955 ,patchBoundaryID(patch.patchBoundary->sID)
969 for(
int d=0;d<
dim;++d)
Class template representing a straight line at the intersection of PlanarMeshFaces.
std::pair< VectorDim, bool > findPatch(const VectorLowerDim &, const VectorDim &)
Eigen::Matrix< double, dim-1, 1 > VectorLowerDim
std::vector< std::shared_ptr< PeriodicPlanePatch< dim > > > filledPatches(const std::vector< VectorDim > &patchShifts)
PeriodicGlidePlane(PeriodicGlidePlaneFactoryType *const pgpf, const KeyType &key_in)
const NodalConnectivityContainerType & neighborConnectivities() const
const NodalConnectivityContainerType & patchConnectivities() const
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
std::set< PeriodicPlaneEdgeType * > InOutEdgeContainerType
auto test(const std::shared_ptr< T > &t)
LatticePlaneKey< dim > GlidePlaneKey
Eigen::Matrix< double, 3, 1 > VectorDim
static VectorDim rightHandedNormal(const std::vector< const PeriodicPlaneEdge< dim > * > &bnd)
void createNewBoundary(const PeriodicPlaneEdge< dim > *currentEdge, UntwinnedEdgeContainerType &untwinnedCopy)
KeyConstructableWeakPtrFactory< PeriodicPatchBoundary< dim >, PeriodicPlaneNode< dim >, typename PeriodicPlaneNode< dim >::CompareType > NodeCointainerType
const PatchContainerType & patches() const
BoundariesContainerType & innerBoundaries()
bool isRightHandedBoundary(const std::vector< const PeriodicPlaneEdge< dim > * > &bnd)
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)
int isInsideOuterBoundary(const VectorLowerDim &test)
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)
NodeCointainerType & nodes()
std::shared_ptr< PeriodicPlaneNode< dim > > getSharedNode(const VectorDim &pointDim, const VectorDim &shift)
BoundariesContainerType & outerBoundaries()
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 &)
PeriodicPlaneEdge< dim > * next
PeriodicPlaneEdge< dim > * nextUntwinned() const
PeriodicPlaneEdge< dim > * prevUntwinned() const
static bool periodicFacesInSameGrain(const std::shared_ptr< const MeshBoundarySegment< dim > > meshIntersection_in)
PeriodicPlaneEdge< dim > * prev
PeriodicPlanePatch(PeriodicPatchBoundary< dim > *const, const VectorDim &)