G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsTriMeshToSolid.hpp
Go to the documentation of this file.
1 
15 #include <gsModeling/gsCurveLoop.h>
18  #include <gsModeling/gsSolid.h>
19  #include <gsNurbs/gsBSpline.h>
20 
21 #include <fstream>
22 
23 namespace gismo
24 {
25 
26 template <class T>
28 {
29  // determine which faces form a big face
30  std::vector<int> added;
31  for (std::vector<int>::size_type i=0;i!=face.size();i++)
32  added.push_back(0);
33  numBigFaces=0;
34  std::stack<FaceHandle> faceCollect;
35  FaceHandle tempFace;
36  for( typename std::vector<FaceHandle >::iterator it(face.begin());it!=face.end();++it)
37  {
38  if (added[(**it).getId()]==0&&
39  *((**it).vertices[0])!=*((**it).vertices[1])&&
40  *((**it).vertices[2])!=*((**it).vertices[1])&&
41  *((**it).vertices[0])!=*((**it).vertices[2]))
42  {
43  numBigFaces++;
44  faceCollect.push(*it);
45  while(!faceCollect.empty())
46  {
47  (*(faceCollect.top())).faceIdentity=numBigFaces;
48  added[(*(faceCollect.top())).getId()]=1;
49  tempFace=faceCollect.top();
50  faceCollect.pop();
51 
52  for (size_t i =0;i<(*tempFace).nFaces.size();i++)
53  {
54  if(added[tempFace->nFaces[i]->getId()]==0)
55  {
56  int k=0;
57  while((*(tempFace->nFaces[i])!=*(edge[tempFace->nEdges[k]->getId()].nFaces[0])&&
58  ((edge[tempFace->nEdges[k]->getId()].nFaces.size()==1)||
59  *(tempFace->nFaces[i])!=*(edge[tempFace->nEdges[k]->getId()].nFaces[1]))))
60  k++;
61  if (edge[tempFace->nEdges[k]->getId()].sharp==0)
62  faceCollect.push((*tempFace).nFaces[i]);
63  }
64  }
65  }
66  }
67  }
68 }
69 
70 
71 template <class T>
72 void gsTriMeshToSolid<T>::getFeatures(T angleGrad,bool& bWarnNonManifold,bool& bWarnBorders)
73 {
74 
75  gsDebug<<"Getting the features..."<<"\n";
76  bWarnNonManifold=false;
77  bWarnBorders=false;
78  //create 3 edges for each face
79  int fsize=face.size();
80  for( int it=0;it<fsize;++it)
81  {
82  for(int i=0;i<3;i++)
83  {
84  VertexHandle p0 = face[it]->vertices[i];
85  VertexHandle p1 = face[it]->vertices[(i+1)%3];
86  if (*p0!=*p1)
87  {
88  if ( Xless<T>(p0,p1) ) std::swap(p0,p1);
89  //Edge tempEdge;
90  //tempEdge=Edge(p0,p1);
91  //insertObject<Edge >(tempEdge,edge);
92  edge.push_sorted_unique( Edge(p0,p1) );
93  }
94  else
95  gsWarn<<"face "<<it<<" has 2 common vertices"<<"\n"<<*p0<<*p1<<"\n";
96  }
97  }
98 
99  numEdges=edge.size();
100  //number the edges
101  int iterId=0;
102  for(typename std::vector<Edge>::iterator iter(edge.begin());iter!=edge.end();++iter)
103  {
104  iter->setId(iterId);
105  iterId++;
106  }
107  //determine neighboring faces of each edge
108  for(size_t it=0;it<face.size();++it)
109  {
110  if(*(face[it]->vertices[0])!=*(face[it]->vertices[1])&&
111  *(face[it]->vertices[2])!=*(face[it]->vertices[1])&&
112  *(face[it]->vertices[0])!=*(face[it]->vertices[2]))
113  {
114  for(int i=0;i<3;i++)
115  {
116  VertexHandle p0 = face[it]->vertices[i];
117  VertexHandle p1 = face[it]->vertices[(i+1)%3];
118  if ( Xless<T>(p0,p1) ) std::swap(p0,p1);
119  //Edge tempEdge;
120  //tempEdge=Edge(p0,p1);
121  //edge[getIndex<Edge>(tempEdge,edge)].nFaces.push_back(face[it]);
122  Edge * eit = edge.find_ptr_or_fail( Edge(p0,p1) );
123 
124  eit->nFaces.push_back(face[it]);
125 
126  //face[it]->nEdges.push_back(&edge[getIndex<Edge>(tempEdge,edge)]);
127  face[it]->nEdges.push_back(eit);
128  }
129  }
130  }
131 
132  // Extract those edges whose adjacent triangles form a large angle
133  for(typename std::vector<Edge>::iterator iter(edge.begin());iter!=edge.end();++iter)
134  {
135  std::vector<FaceHandle > vT;
136  for (size_t i=0;i<iter->nFaces.size();i++)
137  {
138  vT.push_back(iter->nFaces[i]);
139  }
140  if(vT.size()==1)
141  {
142  bWarnBorders=true;
143  iter->sharp=1;
144  continue;
145  }
146  if(vT.size()>2)
147  {
148  bWarnNonManifold=true;
149  gsWarn<<"non manifold edge"<<"\n";
150  iter->sharp=1;
151  continue;
152  }
153  GISMO_ASSERT(vT.size()==2, "Edge must belong to two triangles, got "<<vT.size() );
154  gsVector3d<T> nv0((*vT[0]).orthogonalVector());
155  nv0 = nv0/(math::sqrt(nv0.squaredNorm()));
156  gsVector3d<T> nv1((*vT[1]).orthogonalVector());
157  nv1 = nv1/(math::sqrt(nv1.squaredNorm()));
158  T cosPhi( nv0.dot(nv1) );
159  // Numerical robustness
160  if(cosPhi > (T)(1.0)) cosPhi = (T)(1.0);
161  else if(cosPhi < (T)(-1.0)) cosPhi = (T)(-1.0);
162 
163  const T PI_(3.14159);
164  T phiGrad(math::acos(cosPhi)/PI_*(T)(180));
165  if(phiGrad>=angleGrad)
166  iter->sharp=1;
167  else
168  iter->sharp=0;
169 
170  (*face[(*vT[0]).getId()]).nFaces.push_back(face[(*vT[1]).getId()]);
171  (*face[(*vT[1]).getId()]).nFaces.push_back(face[(*vT[0]).getId()]);
172  }
173 
174  if(bWarnNonManifold)
175  {
176  gsDebug<<"Attention: There were non-manifold edges. These are always features"<<"\n";
177  }
178  if(bWarnBorders)
179  {
180  gsDebug<<"Attention: There were border edges. These are always features"<<"\n";
181  }
182 }
183 
184 template <class T>
185 void gsTriMeshToSolid<T>::setSharpEdges(std::vector< gsEdge<T> > & featEdges, int useFeatures)
186 {
187  if(useFeatures==1||useFeatures==2)
188  {
189  if(useFeatures==2)
190  {
191  for(size_t i=0;i<edge.size();i++)
192  {
193  edge[i].sharp=0;
194  }
195  }
196  for(size_t i=0;i<featEdges.size();i++)
197  {
198  bool foundEdge=0;
199  for(size_t j=0;j<edge.size();j++)
200  {
201  if(approxEqual(featEdges[i],edge[j])==1)
202  {
203  edge[j].sharp=1;
204  foundEdge=1;
205  }
206  }
207  if (foundEdge==0)
208  gsWarn<<"could not find the feature number"<<i<<",review the input data"<<"\n";
209  }
210  }
211  int i1=0;
212  for(typename std::vector<Edge>::iterator iter(edge.begin());iter!=edge.end();++iter)
213  {
214  if(iter->sharp==1)
215  i1++;
216  }
217  gsDebug<<"Feature lines: "<<i1<<"\n";
218 }
219 
220 
221 template <class T>
223 {
224  //store information about the neighboring faces of each edge in the edges
225  for (typename std::vector<Edge >::iterator it(edge.begin());it!=edge.end();++it)
226  {
227  if ((*it).nFaces[0]->faceIdentity==(*it).nFaces[1]->faceIdentity)
228  (*it).numPatches.push_back((*it).nFaces[0]->faceIdentity);
229  else
230  {
231  (*it).numPatches.push_back((*it).nFaces[0]->faceIdentity);
232  (*it).numPatches.push_back((*it).nFaces[1]->faceIdentity);
233  }
234  }
235 }
236 
237 
238 template <class T>
239 void gsTriMeshToSolid<T>::divideAndMergePatches(T innerAngle, T patchAreaWeight, T mergeSmallPatches)
240 {
241  //calculate areas of the patches
242  std::vector<T > areas;
243  for (int i=0;i<numBigFaces;i++)
244  areas.push_back(0);
245  for (size_t i=0;i<face.size();i++)
246  {
247  if(face[i]->faceIdentity>0&&face[i]->faceIdentity<=numBigFaces)
248  areas[face[i]->faceIdentity-1]+=calcArea(face[i]);
249  }
250  T totalArea=0;
251  for(size_t i=0;i<areas.size();i++)
252  {
253  //gsDebug<<"area of ith patch: "<<areas[i]<<"\n";
254  totalArea+=areas[i];
255  }
256  T averageArea=totalArea/static_cast<T>(areas.size());
257  for(size_t j=0;j<edge.size();j++)
258  {
259  if(edge[j].numPatches.size()==1)
260  {
261 
262  if(areas[edge[j].numPatches[0]-1]>averageArea*patchAreaWeight)
263  {
264 
265  gsVector3d<T> nv0(edge[j].nFaces[0]->orthogonalVector());
266  nv0 = nv0/(math::sqrt(nv0.squaredNorm()));
267  gsVector3d<T> nv1(edge[j].nFaces[1]->orthogonalVector());
268  nv1 = nv1/(math::sqrt(nv1.squaredNorm()));
269  T cosPhi( nv0.dot(nv1) );
270  // Numerical robustness
271  if(cosPhi > (T)(1.0)) cosPhi = (T)(1.0);
272  else if(cosPhi < (T)(-1.0)) cosPhi = (T)(-1.0);
273 
274  const T PI_(3.14159);
275  T phiGrad(math::acos(cosPhi)/PI_*(T)(180));
276  if(phiGrad>=innerAngle)
277  edge[j].sharp=1;
278  else
279  edge[j].sharp=0;
280  }
281  }
282  }
283  int i2=0;
284  for(typename std::vector<Edge>::iterator iter(edge.begin());iter!=edge.end();++iter)
285  {
286  if(iter->sharp==1)
287  i2++;
288  }
289  gsDebug<<"Feature lines after dividing patches: "<<i2<<"\n";
290  if(mergeSmallPatches!=0)
291  {
292  for(size_t j=0;j<edge.size();j++)
293  {
294  if(edge[j].numPatches.size()==2)
295  {
296  if(areas[edge[j].numPatches[0]-1]<averageArea*mergeSmallPatches&&areas[edge[j].numPatches[1]-1]<averageArea*mergeSmallPatches)
297  edge[j].sharp=0;
298  }
299  }
300  }
301  int i3=0;
302  for(typename std::vector<Edge>::iterator iter(edge.begin());iter!=edge.end();++iter)
303  {
304  if(iter->sharp==1)
305  i3++;
306  }
307  gsDebug<<"Feature lines after merging patches: "<<i3<<"\n";
308 }
309 
310 template <class T>
311 void gsTriMeshToSolid<T>::getFaces(std::vector<std::vector<VertexHandle> > & iPoints, std::vector<std::vector<VertexHandle> > & oPoints,
312  std::vector< std::vector<std::vector<VertexHandle> > > & innerBdrys, std::vector< std::vector<Vertex> > & innerBdrysMassP,
313  std::vector<std::vector<bool> > & oPointsConvexFlag)
314 {
315  gsDebug<<"Getting the faces..."<<"\n";
316  this->calcPatchNumbers();
317 
318  //eliminate sharp edges in the interior of big faces
319  for (typename std::vector<Edge >::iterator it(edge.begin());it!=edge.end();++it)
320  {
321  if ((*it).sharp==1&&(*it).nFaces[0]->faceIdentity==(*it).nFaces[1]->faceIdentity)
322  (*it).sharp=0;
323  }
324  //determine sharp attribute for vertices
325  for (size_t i=0;i<edge.size();i++)
326  {
327  edge[i].source->nVertices.push_back(edge[i].target);
328  edge[i].target->nVertices.push_back(edge[i].source);
329  if (edge[i].sharp==1)
330  {
331  edge[i].source->sharp=1;
332  edge[i].target->sharp=1;
333  }
334  else
335  {
336  if(edge[i].source->sharp!=1)
337  edge[i].source->sharp=0;
338  if(edge[i].target->sharp!=1)
339  edge[i].target->sharp=0;
340  }
341  }
342  // put all sharp edges of a big face in a multimap
343  std::multimap<int,EdgeHandle> mmIE;
344  for (typename std::vector<Edge >::iterator it(edge.begin());it!=edge.end();++it)
345  {
346  if ((*it).sharp==1&&(*it).nFaces[0]->faceIdentity!=(*it).nFaces[1]->faceIdentity)
347  {
348  if ((*it).nFaces.size()!=2)
349  gsDebug<<"edge "<<*it<<" has "<<(*it).nFaces.size()<<" neighboring faces"<<"\n";
350  mmIE.insert(std::make_pair((*it).nFaces[0]->faceIdentity,&(*it)));
351  mmIE.insert(std::make_pair((*it).nFaces[1]->faceIdentity,&(*it)));
352  }
353  }
354  for (std::vector<int>::size_type i=0;i!=vertex.size();i++)
355  vertex[i]->numEdges=0;
356  for( typename std::vector<Edge >::iterator it(edge.begin());it!=edge.end();++it)
357  {
358  if((*it).nFaces.size()==2&&((*it).nFaces[0]->faceIdentity!=(*it).nFaces[1]->faceIdentity))
359  {
360  vertex[(*it).source->getId()]->numEdges++;
361  vertex[(*it).target->getId()]->numEdges++;
362  }
363  }
364 
365  gsDebug<<"Getting interior points..."<<"\n";
366  //calculating interior points of each big face
367  std::vector< std::set< VertexHandle> > iPointsSet;
368  std::set< VertexHandle > vertexSet;
369 
370  // first set up iPointsSet[i] for each i, which is the set of all
371  // vertices that are on some triangle belonging to big face i
372  for (int i=0;i<numBigFaces;i++)
373  {
374  iPointsSet.push_back(vertexSet);
375  }
376  for( typename std::vector<FaceHandle >::iterator it(face.begin());it!=face.end();++it)
377  {
378  if ( *((**it).vertices[0])!=*((**it).vertices[1])&&
379  *((**it).vertices[2])!=*((**it).vertices[1])&&
380  *((**it).vertices[0])!=*((**it).vertices[2]))
381  {
382  for (int i=0;i<3;i++)
383  {
384  iPointsSet[(**it).faceIdentity-1].insert((**it).vertices[i]);
385  }
386  }
387  }
388 
389  // now, for each i, set up iPoints[i] which consists of those elements
390  // of iPointsSet[i] that are sharp vertices.
391  for(int i=0;i<numBigFaces;i++)
392  {
393  std::vector< VertexHandle > tempVec;
394  for (typename std::set<VertexHandle> ::iterator it(iPointsSet[i].begin());it!=iPointsSet[i].end();++it)
395  {
396  if((**it).sharp==0)
397  tempVec.push_back(*it);
398  }
399  iPoints.push_back(tempVec);
400  }
401 
402 
403  gsDebug<<"Getting boundary points..."<<"\n";
404 
405  int sourcePos=0;
406  int targetPos=0;
407 
408  for(int i=1;i<numBigFaces+1;i++)
409  {
410  //check if all boundaries of a face are used
411  bool allEdgesCovered=false;
412  std::vector<bool> edgeAdded;
413  for(size_t j=0;j<mmIE.count(i);j++)
414  edgeAdded.push_back(false);
415  T maxLength=0;
416  T bdryLength=0;
417  std::vector< std::vector<VertexHandle> > innerBdryHelpVec;
418  std::vector<Vertex> innerBdryMassPHelpVec;
419  while (allEdgesCovered==false)
420  {
421  std::vector< bool> isConvex;//required for mapping to a u,v plane
422  std::vector< T> angle; //to calculate isConvex
423  std::vector< VertexHandle> vertexVec; //required for mapping to a u,v plane
424 
425  //take the first edge
426  EdgeHandle firstEdge=mmIE.find(i)->second;
427  int EdgeCount=0;//determine where the first not already used edge is.
428  while (edgeAdded[EdgeCount]==true)
429  EdgeCount++;
430  edgeAdded[EdgeCount]=true;
431  int helpCount=0;
432  for(typename std::multimap<int,EdgeHandle>::iterator edgeIter = mmIE.find(i);helpCount<=EdgeCount;edgeIter++)
433  {
434  helpCount++;
435  firstEdge=(*edgeIter).second;
436  }
437 
438  //use a neighboring face of the first edge to determine the direction of the boundary.
439  FaceHandle firstFace=NULL;
440  if (firstEdge->nFaces[0]->faceIdentity==i)
441  firstFace=firstEdge->nFaces[0];
442  else if(firstEdge->nFaces[1]->faceIdentity==i)
443  firstFace=firstEdge->nFaces[1];
444  else
445  gsWarn<<"edge has wrong neighboring faces"<<"\n";
446  for (int j=0;j<3;j++)
447  {
448  if (*(firstFace->vertices[j])==*(firstEdge->source))
449  sourcePos=j;
450  if (*(firstFace->vertices[j])==*(firstEdge->target))
451  targetPos=j;
452  }
453  if ((sourcePos-targetPos)==1||sourcePos-targetPos==-2)
454  {
455  vertexVec.push_back((firstEdge->target));
456  vertexVec.push_back((firstEdge->source));
457  }
458  else if((sourcePos-targetPos)==2||sourcePos-targetPos==-1)
459  {
460  vertexVec.push_back((firstEdge->source));
461  vertexVec.push_back((firstEdge->target));
462  }
463  else
464  gsWarn<<"Edge not found"<<"\n";
465  //look for an edge with a common vertex and add it to the boundary.
466  EdgeHandle currentEdge=firstEdge;
467  int k=0;
468  while (k==0||(vertexVec[0])!=(vertexVec[vertexVec.size()-1]))
469  {
470  k++;
471  bool edgeNotFound=1;
472  GISMO_UNUSED(edgeNotFound);
473  int l=0;
474  for (typename std::multimap<int,EdgeHandle>::iterator it(mmIE.find(i));(*it).first==i;++it)
475  {
476  if (*(*it).second!=*currentEdge&&*(*it).second->target==*vertexVec[vertexVec.size()-1]&&edgeAdded[l]==false)
477  {
478  vertexVec.push_back(((*it).second->source));
479  //calculate Angle between currentEdge and *it.second
480  angle.push_back(calcAngle(currentEdge,(*it).second,i));
481  currentEdge=(*it).second;
482  edgeNotFound=0;
483  edgeAdded[l]=true;
484  break;
485  }
486  else if (*(*it).second!=*currentEdge&&*(*it).second->source==*vertexVec[vertexVec.size()-1]&&edgeAdded[l]==false)
487  {
488  vertexVec.push_back(((*it).second->target));
489  //calculate Angle between currentEdge and *it.second
490  angle.push_back(calcAngle(currentEdge,(*it).second,i));
491  currentEdge=(*it).second;
492  edgeNotFound=0;
493  edgeAdded[l]=true;
494  break;
495  }
496  l++;
497 
498  }
499  //calculate angle between first and last edge.
500  if (*(vertexVec[0])==*(vertexVec[vertexVec.size()-1]))
501  {
502  typename std::vector<T>::iterator it=angle.begin();
503  angle.insert(it,calcAngle(currentEdge, firstEdge,i));
504  }
505  GISMO_ASSERT(edgeNotFound==0,"edge not found, could not create a closed boundary of sharp edges to identify a face");
506  }
507 
508  for (size_t j=0;j<angle.size();j++)
509  {
510  isConvex.push_back(angle[j] < (T)(EIGEN_PI));
511  }
512  //first vertex is added 2 times -> delete last one
513  vertexVec.pop_back();
514 
515  //store the data of the outer boundary.
516  bdryLength=calcBdryLength(vertexVec);
517  if (maxLength==0)
518  {
519  oPoints.push_back(vertexVec);
520  maxLength=bdryLength;
521  oPointsConvexFlag.push_back(isConvex);
522  }
523  else if (bdryLength>maxLength)
524  {
525  innerBdryHelpVec.push_back(oPoints.back());
526  innerBdryMassPHelpVec.push_back(getMassP(oPoints.back()));
527  oPoints.pop_back();
528  oPoints.push_back(vertexVec);
529  maxLength=bdryLength;
530  oPointsConvexFlag.pop_back();
531  oPointsConvexFlag.push_back(isConvex);
532  }
533  else if(bdryLength<=maxLength)
534  {
535  innerBdryHelpVec.push_back(vertexVec);
536  innerBdryMassPHelpVec.push_back(getMassP(vertexVec));
537 
538  }
539  //check if all Edges are used yet.
540  allEdgesCovered=true;
541  for (size_t j=0;j<mmIE.count(i);j++)
542  {
543  if (edgeAdded[j]==false)
544  allEdgesCovered=false;
545  }
546  }
547  innerBdrys.push_back(innerBdryHelpVec);
548  innerBdrysMassP.push_back(innerBdryMassPHelpVec);
549  }
550  //establish connections between boundary of a hole in a face and generated point in its interior
551  for(size_t i=0;i<innerBdrys.size();i++)
552  {
553  for(size_t j=0;j<innerBdrys[i].size();j++)
554  {
555  for(size_t k=0;k<innerBdrys[i][j].size();k++)
556  {
557  innerBdrys[i][j][k]->nVertices.push_back(&innerBdrysMassP[i][j]);
558  innerBdrysMassP[i][j].nVertices.push_back(innerBdrys[i][j][k]);
559  }
560  }
561  }
562 
563 }
564 
565 template <class T>
566 void gsTriMeshToSolid<T>::toSolid(gsSolid<T> & sl, std::vector<std::vector<VertexHandle> > & iPoints,
567  std::vector<std::vector<VertexHandle> > & oPoints,
568  std::vector< std::vector<std::vector<VertexHandle> > > & innerBdrys,
569  std::vector< std::vector<Vertex> > & innerBdrysMassP, // articifial points
570  std::vector<std::vector<bool> > & oPointsConvexFlag,
571  std::vector<gsMesh<T> *> & paraMeshes,
572  std::vector<gsMesh<T> *> & fitMeshes,
573  std::vector<gsMesh<T> *> & patchMeshes,
574  int kvOuterPoints, int kvAdditionalInnerPoints,
575  bool plot, int meshPoints,
576  bool moreInner, T wE, T wI, int closeBoundary, bool noSmooth)
577 {
578 
579  GISMO_ASSERT( (static_cast<int>(iPoints.size() ) == numBigFaces) &&
580  (static_cast<int>(oPoints.size() ) == numBigFaces) &&
581  (static_cast<int>(innerBdrys.size() ) == numBigFaces) &&
582  (static_cast<int>(innerBdrysMassP.size() ) == numBigFaces) &&
583  (static_cast<int>(oPointsConvexFlag.size() ) == numBigFaces),
584  "expecting the same number of big faces everywhere");
585 
586  gsDebug<<"mapping to plane..."<<"\n";
587  std::vector<std::vector<Vertex> > iPoints2D;
588  std::vector<std::vector<Vertex> > oPoints2D;
589  std::vector< std::vector<std::vector<Vertex> > > innerBdrys2D;
590 
591  // Create pointers to gsVector3d out of oPoints so that the
592  // gsCurveLoop constructor may be used
593  for (size_t i=0;i<oPoints.size();i++) // for all patches (big faces, given as collection of vertices)
594  {
595 
596  std::vector<gsVector3d<T>*> vertices;
597  std::vector<VertexHandle> vertexVec=oPoints[i];
598 
599  std::vector<bool> isConvex=oPointsConvexFlag[i];
600  for (size_t j=0;j<oPoints[i].size();j++) // for all boundary points of i-th patch
601  {
602  vertices.push_back(&(*vertexVec[j]));
603  }
604 
605  // ---- Construct the boundary curve loop out of the points
606  // start construction
607  gsVector3d<T> faceNormal;
608  gsCurveLoop<T> loop(vertices,isConvex,0.01,&faceNormal);
609  // check curve loop's normal is consistent with triangle normals,
610  // try again with the alternate method if necessary.
611  int nm = normalMult(faceNormal, face, (int)(i + 1));
612  if(nm == 0)
613  {
614  bool success = loop.initFrom3DByAngles(vertices, isConvex, 0.01);
615  // if THAT failed, last ditch effort which will always produce something
616  // but it might not be very good.
617  if(!success)
618  {
619  loop.initFromIsConvex(isConvex, 0.01);
620  }
621  }
622  else if(nm == -1) loop.flip1(); // consistent once we flip
623  // finish construction
624 
625  // Get the parameter pre-images ( 2D points - coefficients of the line segments of the parameter loops)
626  std::vector<gsVertex<T> > vector2D;
627  for(size_t j=0;j<loop.curves().size();j++)
628  {
629  vector2D.push_back(gsVertex<T>(loop.curve(j).coefs()(0,0),loop.curve(j).coefs()(0,1),0));
630  }
631  //calculate the inner 2D Points
632  oPoints2D.push_back(vector2D);
633  }
634  gsDebug<<"generated loops"<<'\n';
635  // calculate areas of the Patches - in case we need to add extra points
636  std::vector<T > areas;
637  for (int i=0;i<numBigFaces;i++)
638  areas.push_back(0);
639  for (size_t i=0;i<face.size();i++)
640  {
641  if(face[i]->faceIdentity>0&&face[i]->faceIdentity<=numBigFaces)
642  areas[face[i]->faceIdentity-1]+=calcArea(face[i]);
643  }
644 
645  T maxArea=0;
646  for (size_t i=0;i<areas.size();i++)
647  if(areas[i]>maxArea)
648  maxArea=areas[i];
649  // Store pointers to all edges of a face, in order to improve the fitting later
650  std::vector< std::vector< EdgeHandle > > faceEdges;
651  for (int i=0;i<numBigFaces;i++) // create container of edges for each patch
652  {
653  std::vector< EdgeHandle > helpVec;
654  faceEdges.push_back(helpVec);
655  }
656  for(size_t i=0;i<edge.size();i++) // for all patches
657  {
658 // GISMO_ASSERT(edge[i].nFaces.size()==2,"each edge has to have 2 nFaces");
659  if(edge[i].nFaces.size()==2 &&
660  ((edge[i].nFaces[0]->faceIdentity)==(edge[i].nFaces[1]->faceIdentity))) // edge in the interior of the patch ?
661  {
662  faceEdges[(edge[i].nFaces[0]->faceIdentity)-1].push_back(&edge[i]);
663  }
664  else // edge on boundary ?
665  {
666  faceEdges[(edge[i].nFaces[0]->faceIdentity)-1].push_back(&edge[i]);
667  if(edge[i].nFaces.size()==2)
668  {
669  faceEdges[(edge[i].nFaces[1]->faceIdentity)-1].push_back(&edge[i]);
670  }
671  }
672  }
673  std::vector<bool> isCylinder; // true if a patch is cylindric shaped
674  std::vector<T> improveCylinderParametrization; // true if a patch is cylindric shaped
675  for(size_t i=0;i<oPoints.size();i++) // For all patches
676  {
677  if(innerBdrys[i].size()!=1) // different than one hole
678  {
679  isCylinder.push_back(0);
680  improveCylinderParametrization.push_back(0);
681  }
682  else // Has one hole ? (then it is cylindrical)
683  {
684  T diameterOut=0; // Measure outer diameter
685  for(size_t j=0;j<oPoints[i].size()-1;j++)
686  {
687  for(size_t k=j+1;k<oPoints[i].size();k++)
688  {
689  T tempDiameter=((oPoints[i][j]->x()-oPoints[i][k]->x())*(oPoints[i][j]->x()-oPoints[i][k]->x()))+
690  ((oPoints[i][j]->y()-oPoints[i][k]->y())*(oPoints[i][j]->y()-oPoints[i][k]->y()))+
691  ((oPoints[i][j]->z()-oPoints[i][k]->z())*(oPoints[i][j]->z()-oPoints[i][k]->z()));
692  if(tempDiameter>diameterOut)
693  diameterOut=tempDiameter;
694  }
695  }
696  T diameterIn=0; // measure inner diameter
697  for(size_t j=0;j<innerBdrys[i][0].size()-1;j++)
698  {
699  for(size_t k=j+1;k<innerBdrys[i][0].size();k++)
700  {
701  T tempDiameter=((innerBdrys[i][0][j]->x()-innerBdrys[i][0][k]->x())*(innerBdrys[i][0][j]->x()-innerBdrys[i][0][k]->x()))+
702  ((innerBdrys[i][0][j]->y()-innerBdrys[i][0][k]->y())*(innerBdrys[i][0][j]->y()-innerBdrys[i][0][k]->y()))+
703  ((innerBdrys[i][0][j]->z()-innerBdrys[i][0][k]->z())*(innerBdrys[i][0][j]->z()-innerBdrys[i][0][k]->z()));
704  if(tempDiameter>diameterIn)
705  diameterIn=tempDiameter;
706  }
707  }
708  T distance=0; // measure height of the cylinder
709  for(size_t j=0;j<oPoints[i].size()-1;j++)
710  {
711  for(size_t k=0;k<innerBdrys[i][0].size();k++)
712  {
713  T tempDist=((oPoints[i][j]->x()-innerBdrys[i][0][k]->x())*(oPoints[i][j]->x()-innerBdrys[i][0][k]->x()))+
714  ((oPoints[i][j]->y()-innerBdrys[i][0][k]->y())*(oPoints[i][j]->y()-innerBdrys[i][0][k]->y()))+
715  ((oPoints[i][j]->z()-innerBdrys[i][0][k]->z())*(oPoints[i][j]->z()-innerBdrys[i][0][k]->z()));
716  if(tempDist<distance||distance==0)
717  distance=tempDist;
718  }
719  }
720  if(diameterOut/(T)(4)<distance&&diameterIn/(T)(4)<distance) // Is this patch a cylinder ??
721  {
722  isCylinder.push_back(1);
723  improveCylinderParametrization.push_back(0.1);// scalar factor for Floater's weight for artificial vertex inside the hole
724  }
725 
726  else
727  {
728  isCylinder.push_back(0);
729  improveCylinderParametrization.push_back(0);
730  }
731  }
732  }
733 
734  // At this point, we have a parametrized boundary point cloud
735  // for each patch, and we go on to obtain a parameterization
736  // of the inner points as well
737 
738  gsDebug<<"allocating surfaces"<<'\n';
739 
740  //allocating the trimmed surfaces
741  std::vector<gsTrimSurface<T> *> tSurfVec;
742  for (size_t i=0;i<iPoints.size();i++) // run through all the patches (big faces)
743  {
744  size_t iPsize=iPoints[i].size();
745  // will contain: TOTAL number of points to map for this
746  // patch ( inner boundary/hole points, artificial points (mass points)
747  // and interior (non boundary) point cloud inside the face
748  size_t n = iPsize+innerBdrysMassP[i].size();
749  size_t innerBdrysSize=0;
750  for (size_t m=0;m<innerBdrys[i].size();m++)
751  {
752  innerBdrysSize+=innerBdrys[i][m].size();
753  }
754  n+=innerBdrysSize;
755 
756  // Construct the 3 important point clouds
757  std::set<VertexHandle> vertexFaceSet; // union of vertexFaceSetBdry and vertexFaceSetInner
758  std::set<VertexHandle> vertexFaceSetBdry; // outer boundary points
759  std::set<VertexHandle> vertexFaceSetInner; // all rest of points apart from outer boundary
760 
761  // --- start Fill up point sets
762  for (size_t j=0;j<iPoints[i].size();j++)
763  {
764  vertexFaceSet.insert(iPoints[i][j]);
765  vertexFaceSetInner.insert(iPoints[i][j]);
766  }
767  for (size_t j=0;j<innerBdrys[i].size();j++)
768  {
769  vertexFaceSet.insert(&innerBdrysMassP[i][j]);
770  vertexFaceSetInner.insert(&innerBdrysMassP[i][j]);
771  for (size_t k=0;k<innerBdrys[i][j].size();k++)
772  {
773  vertexFaceSet.insert(innerBdrys[i][j][k]);
774  vertexFaceSetInner.insert(innerBdrys[i][j][k]);
775  }
776  }
777  for (size_t j=0;j<oPoints[i].size();j++)
778  {
779  vertexFaceSet.insert(oPoints[i][j]);
780  vertexFaceSetBdry.insert(oPoints[i][j]);
781  }
782  // --- end Fill up point sets
783 
784  // ----------------------- Start Floater's algorithm
785  //set up a linear system of equations and solve it in
786  //order to receive a parametrization of the inner points
787  //of a face
788  // u : u-parameter values
789  // v : v-parameter values
790  // b1, b2 : right hand sides of the linera system ( sums of boundary veterx weights or zeros)
791  gsVector<T> u(n) ,v(n) ,b1(n) ,b2(n);
792  // Linear system
793  gsEigen::SparseMatrix<T, ColMajor> A(n,n);
794  gsSparseEntries<T> coefficients;
795  typename gsSparseSolver<T>::LU solver;
796 
797  // idea: Pre-define a map (std::map) from the
798  // vertexhandles to 0...n+k-1, also containing additional
799  // info such as: for instance is it artificial THEN from
800  // vertexhandle we can get the column index, and assemble the
801  // matrix and rhs accordingly without searching every time
802 
803  for (size_t j=0;j<n;j++) //run through all inner points of a single face -- Rows of matrix A
804  {
805  // initialize rhs vector position
806  b1(j)=0;
807  b2(j)=0;
808  coefficients.add(j,j,1.0); // A has ones on the diagonal
809 
810  // --- Local coefficients contributing to point j in the matrix and rhs
811  std::vector<T> rhsCoefs; // weights of the boundary points which are connected to point j
812  std::vector<VertexHandle> rhs; // vertices of right hand side (correst. rhsCoefs)
813  std::vector<T> matCoefs; // weights of the Interiod points which are connected to point j
814  std::vector<VertexHandle> mat; // vertices indexing columns of mat (correst. matCoefs)
815 
816  T check=0;//make sure the weights sum up to 1
817  T normCoef=0; // normalization coefficient, ensures sum of weights at j is equal to 1
818  T weight=0;// temporary
819  if (j<iPsize) // is j an interior point ?
820  {
821  for (size_t k=0;k<iPoints[i][j]->nVertices.size();k++) // searching neighbors of point j
822  {
823  // is it a boundary neighbor ?
824  if(vertexFaceSetBdry.find(iPoints[i][j]->nVertices[k])!=vertexFaceSetBdry.end())
825  {
826  weight=calcWeight(iPoints[i][j],iPoints[i][j]->nVertices[k],vertexFaceSet);
827  rhsCoefs.push_back(weight);
828  rhs.push_back(iPoints[i][j]->nVertices[k]);
829  normCoef+=weight;
830  }
831  else // is it an interior neighbor
832  {
833  weight=calcWeight(iPoints[i][j],iPoints[i][j]->nVertices[k],vertexFaceSet);
834  matCoefs.push_back(weight);
835  mat.push_back(iPoints[i][j]->nVertices[k]);
836  normCoef+=weight;
837  }
838  }
839  }
840  else if(j<iPsize+innerBdrysMassP[i].size()) // is j an artificial point ?
841  {
842  for (size_t k=0;k<innerBdrys[i][j-iPsize].size();k++) // searching neighors of point j
843  {
844  // get weight of artificial point and put it in the matrix
845  weight=calcWeight(&innerBdrysMassP[i][j-iPsize],innerBdrys[i][j-iPsize][k],vertexFaceSet);
846  matCoefs.push_back(weight);
847  mat.push_back(innerBdrys[i][j-iPsize][k]);
848  normCoef+=weight;
849  }
850  }
851  else // is it a point on a hole ? (inner boundary)
852  {
853  // allocate innerbdry points, first all neighbors, last inner point
854 
855  // j ----> k,l (: hole number, point number on k hole)
856 
857  //derive correct indices
858  size_t innerIndex=j-iPsize-innerBdrysMassP[i].size();
859  size_t c=0;
860  size_t k=0;
861  size_t l=0;
862  while (innerIndex>=c)
863  {
864  c+=innerBdrys[i][k].size();
865  k++;
866  }
867  k--;
868  c-=innerBdrys[i][k].size();
869  l=innerIndex-c;
870  // searching neighors of point j
871  for (size_t i2=0;i2<innerBdrys[i][k][l]->nVertices.size();i2++)
872  {
873  // is it a boundary neighbor ?
874  if(vertexFaceSetBdry.find(innerBdrys[i][k][l]->nVertices[i2])!=vertexFaceSetBdry.end())
875  {
876  weight=calcWeight(innerBdrys[i][k][l],(innerBdrys[i][k][l]->nVertices[i2]),vertexFaceSet);
877  rhsCoefs.push_back(weight);
878  rhs.push_back(innerBdrys[i][k][l]->nVertices[i2]);
879  normCoef+=weight;
880  }
881  // is it an interior neighbor
882  else if(vertexFaceSetInner.find(innerBdrys[i][k][l]->nVertices[i2])!=vertexFaceSetInner.end())
883  {
884  weight=calcWeight(innerBdrys[i][k][l],(innerBdrys[i][k][l]->nVertices[i2]),vertexFaceSet);
885  // treating cylindrical patch
886  if(isCylinder[i]==1&&*(innerBdrys[i][k][l]->nVertices[i2])==innerBdrysMassP[i][0])
887  {
888  weight*=improveCylinderParametrization[i];
889  }
890  matCoefs.push_back(weight);
891  mat.push_back(innerBdrys[i][k][l]->nVertices[i2]);
892  normCoef+=weight;
893  }
894  }
895  }
896 
897  GISMO_ASSERT(normCoef > 0, "normCoef should be positive");
898 
899  for (size_t k=0;k<rhsCoefs.size();k++) // for all boundary connections of point j
900  {
901  rhsCoefs[k]=rhsCoefs[k]/normCoef; // normalize coefficient
902  check+=rhsCoefs[k];
903  int l=0;
904  while (*oPoints[i][l]!=*rhs[k]) // locate outer boundary neighbors of point j
905  {
906  l++;
907  }
908  // Fill in right hand side b
909  b1(j)+=(oPoints2D[i][l].operator[](0))*rhsCoefs[k];
910  b2(j)+=(oPoints2D[i][l].operator[](1))*rhsCoefs[k];
911 
912  }
913 
914  for (size_t k=0;k<matCoefs.size();k++) // for all inner/artificial/inner boundary connections of point j
915  {
916  matCoefs[k]=matCoefs[k]/normCoef; // normalize coefficient
917  check+=matCoefs[k];
918 
919  //-- start Locating NON-outer boundary neighbors of j-th point
920  for (size_t l=0;l<iPsize;l++) // search in inner points
921  {
922  if (*mat[k]==*iPoints[i][l])
923  coefficients.add(j,l,-matCoefs[k]);
924  }
925 
926  for (size_t l=0;l<innerBdrysMassP[i].size();l++) // search in artifical points
927  {
928  if(*mat[k]==innerBdrysMassP[i][l])
929  coefficients.add(j,l+iPsize,-matCoefs[k]);
930  }
931 
932  int l=0;
933  for (size_t i2=0;i2<innerBdrys[i].size();i2++) // search in inner boundaries (holes)
934  {
935  for(size_t i3=0;i3<innerBdrys[i][i2].size();i3++)
936  {
937  if(*mat[k]==*innerBdrys[i][i2][i3])
938  coefficients.add(j,l+iPsize+innerBdrysMassP[i].size(),-matCoefs[k]);
939 
940  l++;
941  }
942  }
943  //-- end Locating NON-outer boundary neighbors of j-th point
944  }
945  if(check < (T)(1-0.001)||check > (T)(1+0.001))
946  gsWarn<<"something might have gone wrong with norming: "<<check<<"!=1\n";
947  }
948  //build A from the entries
949  A.setFromTriplets(coefficients.begin(), coefficients.end());
950  //gsDebug<<A<<'\n';
951 
952  if(A.rows()!=0) // If there are interior points
953  {
954  // Compute the ordering permutation vector from the structural pattern of A
955  solver.analyzePattern(A);
956  // Compute the numerical factorization
957  solver.factorize(A);
958  //Use the factors to solve the linear system
959  u = solver.solve(b1);
960  v = solver.solve(b2);
961  }
962  // ----------------------- End Floater's algorithm
963 
964  // ----------------------- Start Fitting
965 
966  std::vector<gsVertex<T> > helpvec;
967  for (size_t j=0;j<iPsize;j++)
968  {
969  helpvec.push_back(gsVertex<T>(u(j),v(j),0));
970  }
971  iPoints2D.push_back(helpvec);
972  std::vector<std::vector<gsVertex<T> > > holeVecFace;
973  int index=innerBdrys[i].size();//ignore the virtual points in the middle of the inner boundarys index=#holes
974  for(size_t j=0;j<innerBdrys[i].size();j++)
975  {
976  std::vector<gsVertex<T> > holeVec;
977  for(size_t k=0;k<innerBdrys[i][j].size();k++)
978  {
979  holeVec.push_back(gsVertex<T>(u(iPsize+index),v(iPsize+index),0));
980  index++;
981  }
982  holeVecFace.push_back(holeVec);
983  }
984  innerBdrys2D.push_back(holeVecFace);
985 
986  //altering data to gsMatrix-form, in order to use a fitting function
987  int nCorners=0;
988  for (size_t j=0;j<oPoints[i].size();j++)
989  {
990  if(oPoints[i][j]->numEdges>2)
991  {
992  nCorners++;
993  }
994  }
995  for (size_t j=0;j<innerBdrys[i].size();j++)
996  {
997  for(size_t k=0;k<innerBdrys[i][j].size();k++)
998  {
999  if(innerBdrys[i][j][k]->numEdges>2)
1000  {
1001  nCorners++;
1002  }
1003  }
1004  }
1005  gsMatrix<T> Corners2d(2,nCorners);
1006  gsMatrix<T> Corners3d(3,nCorners);
1007  int nEdgePts=(oPoints[i].size()+innerBdrysSize)*(closeBoundary+1)-nCorners;
1008 
1009  gsMatrix<T> EdgePts2d(2,nEdgePts);
1010  gsMatrix<T> EdgePts3d(3,nEdgePts);
1011  int corNum=0;
1012  int edgNum=0;
1013  for (size_t j=0;j<oPoints[i].size();j++)
1014  {
1015 
1016  if(oPoints[i][j]->numEdges>2)
1017  {
1018  Corners2d(0,corNum)=oPoints2D[i][j].x();
1019  Corners2d(1,corNum)=oPoints2D[i][j].y();
1020  Corners3d(0,corNum)=oPoints[i][j]->x();
1021  Corners3d(1,corNum)=oPoints[i][j]->y();
1022  Corners3d(2,corNum)=oPoints[i][j]->z();
1023  corNum++;
1024  }
1025  else
1026  {
1027  EdgePts2d(0,edgNum)=oPoints2D[i][j].x();
1028  EdgePts2d(1,edgNum)=oPoints2D[i][j].y();
1029  EdgePts3d(0,edgNum)=oPoints[i][j]->x();
1030  EdgePts3d(1,edgNum)=oPoints[i][j]->y();
1031  EdgePts3d(2,edgNum)=oPoints[i][j]->z();
1032  edgNum++;
1033  }
1034  }
1035  for(size_t j=0;j<oPoints[i].size()-1;j++)
1036  {
1037  for(int k=0;k<closeBoundary;k++)
1038  {
1039  EdgePts2d(0,edgNum)=oPoints2D[i][j].x()*(T)(k+1)/(T)(closeBoundary+1)+oPoints2D[i][j+1].x()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1040  EdgePts2d(1,edgNum)=oPoints2D[i][j].y()*(T)(k+1)/(T)(closeBoundary+1)+oPoints2D[i][j+1].y()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1041  EdgePts3d(0,edgNum)=oPoints[i][j]->x()*(T)(k+1)/(T)(closeBoundary+1)+oPoints[i][j+1]->x()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1042  EdgePts3d(1,edgNum)=oPoints[i][j]->y()*(T)(k+1)/(T)(closeBoundary+1)+oPoints[i][j+1]->y()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1043  EdgePts3d(2,edgNum)=oPoints[i][j]->z()*(T)(k+1)/(T)(closeBoundary+1)+oPoints[i][j+1]->z()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1044  edgNum++;
1045  }
1046  }
1047  for(int k=0;k<closeBoundary;k++)
1048  {
1049  EdgePts2d(0,edgNum)=oPoints2D[i][0].x()*(T)(k+1)/(T)(closeBoundary+1)+oPoints2D[i].back().x()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1050  EdgePts2d(1,edgNum)=oPoints2D[i][0].y()*(T)(k+1)/(T)(closeBoundary+1)+oPoints2D[i].back().y()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1051  EdgePts3d(0,edgNum)=oPoints[i][0]->x()*(T)(k+1)/(T)(closeBoundary+1)+oPoints[i].back()->x()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1052  EdgePts3d(1,edgNum)=oPoints[i][0]->y()*(T)(k+1)/(T)(closeBoundary+1)+oPoints[i].back()->y()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1053  EdgePts3d(2,edgNum)=oPoints[i][0]->z()*(T)(k+1)/(T)(closeBoundary+1)+oPoints[i].back()->z()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1054  edgNum++;
1055  }
1056 
1057  int nInteriorPts=iPsize;
1058  //calculate number of additional inner Points
1059  std::multiset<T> edgeLengths;
1060  std::vector<int> nAddIntPointsPerEdge;
1061  int nAddIntPoints=0;
1062  if(moreInner)
1063  {
1064  T h=0;
1065  for(size_t j=0;j<faceEdges[i].size();j++)
1066  {
1067  edgeLengths.insert(calcDist(faceEdges[i][j]->source,faceEdges[i][j]->target));
1068  }
1069  //for(typename std::multiset<T >::iterator it=edgeLengths.begin();j!=edgeLengths.size()/10;it++)
1070  typename std::multiset<T >::iterator it=edgeLengths.begin();
1071  for(size_t j=0;j<=edgeLengths.size()/10;j++)
1072  {
1073  h=*it;
1074  it++;
1075  }
1076  for(size_t j=0;j<faceEdges[i].size();j++)
1077  {
1078  T l=calcDist(faceEdges[i][j]->source,faceEdges[i][j]->target);
1079  int add= math::max( cast<T,int>(l/h)-1, 0 );
1080  nAddIntPointsPerEdge.push_back(add);
1081  nAddIntPoints+=add;
1082  }
1083  }
1084  gsMatrix<T> interiorPts2d(2,nInteriorPts+nAddIntPoints);
1085  gsMatrix<T> interiorPts3d(3,nInteriorPts+nAddIntPoints);
1086  for (size_t j=0;j<iPoints2D[i].size();j++)
1087  {
1088  {
1089  interiorPts2d(0,j)=iPoints2D[i][j].x();
1090  interiorPts2d(1,j)=iPoints2D[i][j].y();
1091  interiorPts3d(0,j)=iPoints[i][j]->x();
1092  interiorPts3d(1,j)=iPoints[i][j]->y();
1093  interiorPts3d(2,j)=iPoints[i][j]->z();
1094  }
1095  }
1096  int intNum=iPsize;
1097  if(moreInner)
1098  {
1099  for(size_t j=0;j<faceEdges[i].size();j++)
1100  {
1101  if(nAddIntPointsPerEdge[j]>0)
1102  {
1103  VertexHandle v1=NULL;
1104  VertexHandle v2=NULL;
1105  VertexHandle v1_2d=NULL;
1106  VertexHandle v2_2d=NULL;
1107 
1108  //find source and target of edge
1109  for(size_t k=0;k<oPoints[i].size();k++)
1110  {
1111  if(oPoints[i][k]==faceEdges[i][j]->source)
1112  {
1113  v1=oPoints[i][k];
1114  v1_2d=&oPoints2D[i][k];
1115  }
1116  else if(oPoints[i][k]==faceEdges[i][j]->target)
1117  {
1118  v2=oPoints[i][k];
1119  v2_2d=&oPoints2D[i][k];
1120  }
1121  }
1122  for(size_t k=0;k<iPoints[i].size();k++)
1123  {
1124  if(iPoints[i][k]==faceEdges[i][j]->source)
1125  {
1126  v1=iPoints[i][k];
1127  v1_2d=&iPoints2D[i][k];
1128  }
1129  else if(iPoints[i][k]==faceEdges[i][j]->target)
1130  {
1131  v2=iPoints[i][k];
1132  v2_2d=&iPoints2D[i][k];
1133  }
1134  }
1135  for(size_t k=0;k<innerBdrys[i].size();k++)
1136  {
1137  for(size_t l=0;l<innerBdrys[i][k].size();l++)
1138  {
1139  if(innerBdrys[i][k][l]==faceEdges[i][j]->source)
1140  {
1141  v1=innerBdrys[i][k][l];
1142  v1_2d=&innerBdrys2D[i][k][l];
1143  }
1144  else if(innerBdrys[i][k][l]==faceEdges[i][j]->target)
1145  {
1146  v2=innerBdrys[i][k][l];
1147  v2_2d=&innerBdrys2D[i][k][l];
1148  }
1149  }
1150  }
1151  GISMO_ASSERT(v1!=NULL&&v2!=NULL,"could not find source or target of the edge in the face");
1152  for (int k=0;k<nAddIntPointsPerEdge[j];k++)
1153  {
1154  interiorPts2d(0,intNum)=v1_2d->x()*(T)(k+1)/(T)(nAddIntPointsPerEdge[j]+1)+
1155  v2_2d->x()*(T)(nAddIntPointsPerEdge[j]-k)/(T)(nAddIntPointsPerEdge[j]+1);
1156  interiorPts2d(1,intNum)=v1_2d->y()*(T)(k+1)/(T)(nAddIntPointsPerEdge[j]+1)+
1157  v2_2d->y()*(T)(nAddIntPointsPerEdge[j]-k)/(T)(nAddIntPointsPerEdge[j]+1);
1158  interiorPts3d(0,intNum)=v1->x()*(T)(k+1)/(T)(nAddIntPointsPerEdge[j]+1)+
1159  v2->x()*(T)(nAddIntPointsPerEdge[j]-k)/(T)(nAddIntPointsPerEdge[j]+1);
1160  interiorPts3d(1,intNum)=v1->y()*(T)(k+1)/(T)(nAddIntPointsPerEdge[j]+1)+
1161  v2->y()*(T)(nAddIntPointsPerEdge[j]-k)/(T)(nAddIntPointsPerEdge[j]+1);
1162  interiorPts3d(2,intNum)=v1->z()*(T)(k+1)/(T)(nAddIntPointsPerEdge[j]+1)+
1163  v2->z()*(T)(nAddIntPointsPerEdge[j]-k)/(T)(nAddIntPointsPerEdge[j]+1);
1164  intNum++;
1165  }
1166 
1167  }
1168  }
1169  }
1170  for(size_t j=0;j<innerBdrys[i].size();j++)
1171  {
1172  for(size_t k=0;k<innerBdrys[i][j].size();k++)
1173  {
1174  if(innerBdrys[i][j][k]->numEdges>2)
1175  {
1176  Corners2d(0,corNum)=innerBdrys2D[i][j][k].x();
1177  Corners2d(1,corNum)=innerBdrys2D[i][j][k].y();
1178  Corners3d(0,corNum)=innerBdrys[i][j][k]->x();
1179  Corners3d(1,corNum)=innerBdrys[i][j][k]->y();
1180  Corners3d(2,corNum)=innerBdrys[i][j][k]->z();
1181  corNum++;
1182  }
1183  else
1184  {
1185  EdgePts2d(0,edgNum)=innerBdrys2D[i][j][k].x();
1186  EdgePts2d(1,edgNum)=innerBdrys2D[i][j][k].y();
1187  EdgePts3d(0,edgNum)=innerBdrys[i][j][k]->x();
1188  EdgePts3d(1,edgNum)=innerBdrys[i][j][k]->y();
1189  EdgePts3d(2,edgNum)=innerBdrys[i][j][k]->z();
1190  edgNum++;
1191  }
1192  }
1193  }
1194  for(size_t it=0;it<innerBdrys[i].size();it++)
1195  {
1196  for(size_t j=0;j<innerBdrys[i][it].size()-1;j++)
1197  {
1198  for(int k=0;k<closeBoundary;k++)
1199  {
1200  EdgePts2d(0,edgNum)=innerBdrys2D[i][it][j].x()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys2D[i][it][j+1].x()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1201  EdgePts2d(1,edgNum)=innerBdrys2D[i][it][j].y()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys2D[i][it][j+1].y()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1202  EdgePts3d(0,edgNum)=innerBdrys[i][it][j]->x()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys[i][it][j+1]->x()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1203  EdgePts3d(1,edgNum)=innerBdrys[i][it][j]->y()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys[i][it][j+1]->y()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1204  EdgePts3d(2,edgNum)=innerBdrys[i][it][j]->z()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys[i][it][j+1]->z()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1205  edgNum++;
1206  }
1207  }
1208  for(int k=0;k<closeBoundary;k++)
1209  {
1210  EdgePts2d(0,edgNum)=innerBdrys2D[i][it][0].x()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys2D[i][it].back().x()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1211  EdgePts2d(1,edgNum)=innerBdrys2D[i][it][0].y()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys2D[i][it].back().y()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1212  EdgePts3d(0,edgNum)=innerBdrys[i][it][0]->x()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys[i][it].back()->x()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1213  EdgePts3d(1,edgNum)=innerBdrys[i][it][0]->y()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys[i][it].back()->y()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1214  EdgePts3d(2,edgNum)=innerBdrys[i][it][0]->z()*(T)(k+1)/(T)(closeBoundary+1)+innerBdrys[i][it].back()->z()*(T)(closeBoundary-k)/(T)(closeBoundary+1);
1215  edgNum++;
1216  }
1217  }
1218  gsMatrix<T> appxNormalPoints(2,0);
1219  gsMatrix<T> appxNormals(3,0);
1220  int innerPts=cast<T,int>(math::sqrt(cast<int,T>(nCorners+kvAdditionalInnerPoints)));
1221  if (innerPts<0)
1222  innerPts=0;
1223 
1224  gsKnotVector<T> kv1 (0, 1, innerPts, kvOuterPoints) ;
1225 
1227  Corners2d, Corners3d,
1228  EdgePts2d, EdgePts3d,
1229  interiorPts2d, interiorPts3d,
1230  appxNormalPoints, appxNormals,
1231  (T)(wE), (T)(wI), (T)(0), (T)(0.01),
1232  kv1,kv1,
1233  false
1234  );
1235  // ----------------------- End Fitting
1236 
1237  // ----------- start Calculate trimmed surfaces
1238  std::vector< gsCurveLoop<T> *> loops;
1239  gsCurveLoop<T> * loop = calculateLoop(oPoints2D[i], isCorner(oPoints[i]), noSmooth);
1240 
1241  loops.push_back(loop);
1242  for (size_t j=0;j<innerBdrys2D[i].size();j++)
1243  {
1244  gsCurveLoop<T> * innerloop = calculateLoop(innerBdrys2D[i][j], isCorner(innerBdrys[i][j]), noSmooth);
1245  loops.push_back(innerloop);
1246  }
1247  gsPlanarDomain<T> * domain= new gsPlanarDomain<T>(loops);
1248  gsTrimSurface<T> * cface= new gsTrimSurface<T> (spline,domain);
1249  tSurfVec.push_back(cface);
1250 
1251  if(plot) // for debugging ( plot trimmed surfaces
1252  {
1253  typename gsMesh<T>::uPtr m;
1254  int nPoints=cast<T,int>(
1255  (T)(meshPoints)*math::sqrt(math::sqrt(areas[i]/maxArea)));
1256  if (nPoints<10)
1257  nPoints=10;
1258  m = cface->toMesh(nPoints);
1259  fitMeshes.push_back(m.release());
1260  }
1261 
1262  // ----------- end Calculate trimmed surfaces
1263 
1264  //delete cface;
1265 
1266  } // End main loop over patches / big faces
1267 
1268  //allocate gsSolid
1269  //std::vector<gsVertex<T> > vertVec; // ---sorted
1270  gsSortedVector<gsVertex<T> > vertVec;
1271  for (size_t i=0;i<oPoints.size();i++)
1272  {
1273  for (size_t j=0;j<oPoints[i].size();j++)
1274  {
1275  //insertObject(*oPoints[i][j],vertVec);
1276  vertVec.push_sorted_unique(*oPoints[i][j]);
1277  }
1278  }
1279  for (size_t i=0;i<innerBdrys.size();i++)
1280  {
1281  for (size_t j=0;j<innerBdrys[i].size();j++)
1282  {
1283  for(size_t k=0;k<innerBdrys[i][j].size();k++)
1284  //insertObject(*innerBdrys[i][j][k],vertVec);
1285  vertVec.push_sorted_unique(*innerBdrys[i][j][k]);
1286  }
1287  }
1288  for (size_t i=0;i<vertVec.size();i++)
1289  sl.addHeVertex(vertVec[i][0],vertVec[i][1],vertVec[i][2]);
1290  for (size_t i=0;i<oPoints.size();i++)
1291  {
1292  std::vector<std::vector<gsSolidHeVertex<T>* > > faceConstruct;
1293  std::vector<gsSolidHeVertex<T>* > faceHelp;
1294  for (size_t j=0;j<oPoints[i].size();j++)
1295  {
1296  //faceHelp.push_back(sl.vertex[getIndex(*oPoints[i][j],vertVec)]);
1297  faceHelp.push_back( sl.vertex[ vertVec.getIndex(*oPoints[i][j])] );
1298  }
1299  faceConstruct.push_back(faceHelp);
1300  for (size_t j=0;j<innerBdrys[i].size();j++)
1301  {
1302  faceHelp.clear();
1303  for (size_t k=0;k<innerBdrys[i][j].size();k++)
1304  //faceHelp.push_back(sl.vertex[getIndex(*innerBdrys[i][j][k],vertVec)]);
1305  faceHelp.push_back( sl.vertex[ vertVec.getIndex(*innerBdrys[i][j][k])] );
1306  faceConstruct.push_back(faceHelp);
1307  }
1308  sl.addFace( faceConstruct, tSurfVec[i]);
1309 
1310  }
1311 
1312  // Now: only members 'mate' of halfedge is missing, we will set them up now
1313 
1314  sl.setHeMate();
1315  // Add volume
1316 
1317  sl.addVolume(sl.face);
1318  // test what the faces look like
1319  if(plot) // for debugging, plot original meshes
1320  {
1321  for(int facenumber=1;facenumber<=numBigFaces;facenumber++) // for all patches
1322  {
1323 
1324  gsMesh<T> * mface = new gsMesh<T>();
1325  for (size_t it=0;it<this->face.size();it++)
1326  {
1327  if(this->face[it]->faceIdentity==facenumber)
1328  {
1329 
1330  mface->addVertex(this->face[it]->vertices[0]->operator[](0),
1331  this->face[it]->vertices[0]->operator[](1),
1332  this->face[it]->vertices[0]->operator[](2));
1333 
1334  mface->addVertex(this->face[it]->vertices[1]->operator[](0),
1335  this->face[it]->vertices[1]->operator[](1),
1336  this->face[it]->vertices[1]->operator[](2));
1337 
1338  mface->addVertex(this->face[it]->vertices[2]->operator[](0),
1339  this->face[it]->vertices[2]->operator[](1),
1340  this->face[it]->vertices[2]->operator[](2));
1341  }
1342  }
1343 
1344  for (size_t i=0;i!=mface->numVertices();i=i+3)
1345  {
1346  (mface)->addFace(&mface->vertex(i), &mface->vertex(i+1), &mface->vertex(i+2));
1347  }
1348  patchMeshes.push_back(mface);
1349 
1350 
1351  gsMesh<T> * paraface=new gsMesh<T>();
1352  for(size_t it=0;it<this->face.size();it++)
1353  {
1354  if(this->face[it]->faceIdentity==facenumber)
1355  {
1356  for(size_t vertIt=0;vertIt<3;vertIt++)
1357  {
1358  bool found=0;
1359  for(size_t j=0;j<oPoints[facenumber-1].size();j++)
1360  {
1361  if(*this->face[it]->vertices[vertIt]==*oPoints[facenumber-1][j]&&found==0)
1362  {
1363 
1364  paraface->addVertex(oPoints2D[facenumber-1][j][0],oPoints2D[facenumber-1][j][1],0);
1365  found=1;
1366  }
1367  }
1368  for(size_t j=0;j<iPoints[facenumber-1].size();j++)
1369  {
1370  if(*this->face[it]->vertices[vertIt]==*iPoints[facenumber-1][j]&&found==0)
1371  {
1372 
1373  paraface->addVertex(iPoints2D[facenumber-1][j][0],iPoints2D[facenumber-1][j][1],0);
1374  found=1;
1375 
1376  }
1377  }
1378  for(size_t j=0;j<innerBdrys[facenumber-1].size();j++)
1379  {
1380  for(size_t k=0;k<innerBdrys[facenumber-1][j].size();k++)
1381  {
1382  if(*this->face[it]->vertices[vertIt]==*innerBdrys[facenumber-1][j][k]&&found==0)
1383  {
1384 
1385  paraface->addVertex(innerBdrys2D[facenumber-1][j][k][0],innerBdrys2D[facenumber-1][j][k][1],0);
1386  found=1;
1387  }
1388  }
1389  }
1390  }
1391  }
1392  }
1393 
1394  for (size_t i=0; i!=paraface->numVertices(); i+=3)
1395  {
1396  (paraface)->addFace(&paraface->vertex(i), &paraface->vertex(i+1), &paraface->vertex(i+2));
1397  }
1398 
1399  paraMeshes.push_back(paraface);
1400  }
1401  }
1402 }
1403 
1404 template <class T>
1405 void gsTriMeshToSolid<T>::getPatchData(T angle, T innerAngle,T patchAreaWeight,T mergeSmallPatches,
1406  std::vector<std::vector<VertexHandle> > & iPoints,
1407  std::vector<std::vector<VertexHandle> > & oPoints,
1408  std::vector< std::vector<std::vector<VertexHandle> > > & innerBdrys,
1409  std::vector< std::vector<Vertex> > & innerBdrysMassP,
1410 
1411  std::vector<std::vector<bool> > & oPointsConvexFlag,
1412  std::string filenameFeatures,
1413  int useFeatures
1414  )
1415 {
1416  bool non_manifold, warning_borders;
1417 
1418  // compute the features
1419  this->getFeatures(angle, non_manifold, warning_borders);
1420  this->mesh->cleanMesh();
1421 
1422  // read features from a file, if required
1423  std::vector<gsEdge<T> > featEdges;
1424  if (useFeatures!=0)
1425  this->readEdges(filenameFeatures, featEdges);
1426  this->setSharpEdges(featEdges, useFeatures);
1427 
1428  // give every face a patch number
1429  this->calcPatchNumbers();
1430 
1431  // improve quality by further dividing and merging patches according to more complex rules
1432  storeNeighboringFaces();
1433  divideAndMergePatches(innerAngle, patchAreaWeight, mergeSmallPatches);
1434 
1435  // recompute patch numbers
1436  this->calcPatchNumbers();
1437 
1438  this->getFaces(iPoints,oPoints,innerBdrys,innerBdrysMassP,oPointsConvexFlag);
1439 
1440 }
1441 
1442 
1443 template <class T>
1444 gsCurveLoop<T> * gsTriMeshToSolid<T>::calculateLoop(std::vector<Vertex> outerPoints, std::vector<bool > const & isCorner, bool noSmooth)
1445 {
1446  GISMO_ASSERT(outerPoints.size()==isCorner.size(),"the vertices have to be defines as corners or edges by a vector of bools");
1447  gsCurveLoop<T> * loop = new gsCurveLoop<T>();
1448  //handle first point
1449  if (noSmooth || isCorner.at(0)==1)
1450  {
1451  if(noSmooth || isCorner.at(1)==1)
1452  {
1453  gsBSpline<T> * tcurve = calcTCurve(outerPoints[0],outerPoints[1]);
1454  loop->insertCurve(tcurve);
1455  }
1456  }
1457  else
1458  {
1459  Vertex v1(0,0,0);
1460  Vertex v2=outerPoints[0];
1461  Vertex v3(0,0,0);
1462  if(isCorner.back()==1)
1463  v1=outerPoints.back();
1464  else
1465  v1=giveMidpoint(outerPoints.back(),outerPoints[0]);
1466  if(isCorner.at(1)==1)
1467  v3=outerPoints[1];
1468  else
1469  v3=giveMidpoint(outerPoints[0],outerPoints[1]);
1470  gsBSpline<T> * tcurve = calcTCurve(v1,v2,v3);
1471  loop->insertCurve(tcurve);
1472  }
1473  //handle points in between
1474  for (size_t i=1;i<outerPoints.size()-1;i++)
1475  {
1476  if (noSmooth || isCorner.at(i)==1)
1477  {
1478  if(noSmooth || isCorner.at(i+1)==1)
1479  {
1480  gsBSpline<T> * tcurve = calcTCurve(outerPoints[i],outerPoints[i+1]);
1481  loop->insertCurve(tcurve);
1482  }
1483  }
1484  else
1485  {
1486  Vertex v1(0,0,0);
1487  Vertex v2=outerPoints[i];
1488  Vertex v3(0,0,0);
1489  if(isCorner.at(i-1)==1)
1490  v1=outerPoints[i-1];
1491  else
1492  v1=giveMidpoint(outerPoints[i-1],outerPoints[i]);
1493  if(isCorner.at(i+1)==1)
1494  v3=outerPoints[i+1];
1495  else
1496  v3=giveMidpoint(outerPoints[i],outerPoints[i+1]);
1497  gsBSpline<T> * tcurve = calcTCurve(v1,v2,v3);
1498  loop->insertCurve(tcurve);
1499  }
1500  }
1501  //handle last point
1502  if (noSmooth || isCorner.back()==1)
1503  {
1504  if(noSmooth || isCorner.at(0)==1)
1505  {
1506  gsBSpline<T> * tcurve = calcTCurve(outerPoints.back(),outerPoints[0]);
1507  loop->insertCurve(tcurve);
1508  }
1509  }
1510  else
1511  {
1512  Vertex v1(0,0,0);
1513  Vertex v2=outerPoints.back();
1514  Vertex v3(0,0,0);
1515  if(isCorner.at(isCorner.size()-2)==1)
1516  v1=outerPoints[isCorner.size()-2];
1517  else
1518  v1=giveMidpoint(outerPoints[isCorner.size()-2],outerPoints.back());
1519  if(isCorner.at(0)==1)
1520  v3=outerPoints[0];
1521  else
1522  v3=giveMidpoint(outerPoints.back(),outerPoints[0]);
1523  gsBSpline<T> * tcurve = calcTCurve(v1,v2,v3);
1524  loop->insertCurve(tcurve);
1525  }
1526 
1527  return loop;
1528 }
1529 
1530 template<class T>
1532  std::set<VertexHandle>
1533  const & vertexFaceSet)
1534 {
1535  T weight = 0;
1536  const gsVector3d<T> vec1 = *v2 - *v1;
1537 
1538  for(size_t i=0;i<v1->nVertices.size();i++)
1539  {
1540  for(size_t j=0;j<v2->nVertices.size();j++)
1541  {
1542  //check if neighboring vertices coincide and if point found is part of the face
1543  if ( *(v1->nVertices[i])==*(v2->nVertices[j]) &&
1544  vertexFaceSet.find(v2->nVertices[j]) != vertexFaceSet.end()
1545  )
1546  {
1547 
1548  const gsVector3d<T> vec2 = *v2->nVertices[j] - *v1;
1549  weight+=math::tan(conditionedAngle( vec1, vec2)/(T)(2));
1550  }
1551  }
1552  }
1553  weight /= calcDist(v1,v2);
1554 
1555  GISMO_ASSERT(weight > 0, "Weight should be positive");
1556 
1557  return weight;
1558 }
1559 
1560 
1561 template <class T>
1563  std::vector<FaceHandle> & face,
1564  int bigFaceIdx)
1565 {
1566  int result = 0;
1567  bool foundResult = false;
1568  // loop over faces
1569  size_t nf = face.size();
1570  // AM: A better way: use am "int count" variable to count the positive inner products
1571  // Then set the result if count==nf or count==0
1572  for(size_t i = 0; i < nf; i++)
1573  {
1574  // check it's a triangle
1575  GISMO_ASSERT(face[i]->vertices.size() == 3, "Expected triangle mesh");
1576  // only look at triangles inside the surface
1577  if(face[i]->faceIdentity != bigFaceIdx) continue;
1578  // compute the normal of this face
1579  const gsVector3d<T> v0 = *face[i]->vertices[0];
1580  const gsVector3d<T> off1 = *face[i]->vertices[1] - v0;
1581  const gsVector3d<T> off2 = *face[i]->vertices[2] - v0;
1582  const gsVector3d<T> thisNormal = off1.cross(off2);
1583  // compare against n and record
1584  T thisResult = thisNormal.dot(globalNormal);
1585  if((foundResult && thisResult * static_cast<T>(result) <= 0) || thisResult == 0)
1586  {
1587  result = 0;
1588  }
1589  else result = (thisResult > 0)?1:-1;
1590  foundResult = true;
1591  }
1592  GISMO_ASSERT(foundResult, "Could not examine any triangles to get normal information");
1593  return result;
1594 }
1595 
1596 template<class T>
1597 bool gsTriMeshToSolid<T>::approxEqual(const gsEdge<T> & e1,const gsEdge<T> & e2)
1598 {
1599  const T epsilon= calcDist(e1.source, e1.target ) * 0.01 ;
1600 
1601  return ( (*e1.source - *e2.source).norm() < epsilon &&
1602  (*e1.target - *e2.target).norm() < epsilon );
1603  /*
1604  bool result=0;
1605  if((e1.source->x()>(e2.source->x()-epsilon))&&((e1.source->x()-epsilon)<e2.source->x())&&
1606  (e1.source->y()>(e2.source->y()-epsilon))&&((e1.source->y()-epsilon)<e2.source->y())&&
1607  (e1.source->z()>(e2.source->z()-epsilon))&&((e1.source->z()-epsilon)<e2.source->z())&&
1608  (e1.target->x()>(e2.target->x()-epsilon))&&((e1.target->x()-epsilon)<e2.target->x())&&
1609  (e1.target->y()>(e2.target->y()-epsilon))&&((e1.target->y()-epsilon)<e2.target->y())&&
1610  (e1.target->z()>(e2.target->z()-epsilon))&&((e1.target->z()-epsilon)<e2.target->z()))
1611  result=1;
1612  return result;
1613  */
1614 }
1615 
1616 template <class T>
1617 T gsTriMeshToSolid<T>::calcAngle(EdgeHandle e1,EdgeHandle e2, int faceNum)
1618 {
1619  VertexHandle anglePoint;
1620  if (e1->source==e2->source||e1->source==e2->target)
1621  anglePoint=e1->source;
1622  else if (e1->target==e2->target||e1->target==e2->source)
1623  anglePoint=e1->target;
1624  else
1625  {
1626  gsDebug<<"Edges are not neighbors"<<"\n";
1627  return 0;
1628  }
1629  gsVector3d<T> vec1(0,0,0);
1630  if (anglePoint==e1->source)
1631  {
1632  gsVector3d<T> helpvec(e1->target->operator[](0)-e1->source->operator[](0),e1->target->operator[](1)-e1->source->operator[](1),e1->target->operator[](2)-e1->source->operator[](2));
1633  vec1 = helpvec;
1634  }
1635  else
1636  {
1637  gsVector3d<T> helpvec(e1->source->operator[](0)-e1->target->operator[](0),e1->source->operator[](1)-e1->target->operator[](1),e1->source->operator[](2)-e1->target->operator[](2));
1638  vec1 = helpvec;
1639  }
1640  gsVector3d<T> vec2(0,0,0);
1641  if (anglePoint==e2->source)
1642  {
1643  gsVector3d<T> helpvec(e2->target->operator[](0)-e2->source->operator[](0),e2->target->operator[](1)-e2->source->operator[](1),e2->target->operator[](2)-e2->source->operator[](2));
1644  vec2 = helpvec;
1645  }
1646  else
1647  {
1648  gsVector3d<T> helpvec(e2->source->operator[](0)-e2->target->operator[](0),e2->source->operator[](1)-e2->target->operator[](1),e2->source->operator[](2)-e2->target->operator[](2));
1649  vec2=helpvec;
1650  }
1651  FaceHandle vec1Face=NULL;
1652  FaceHandle vec2Face=NULL;
1653 
1654  if (e1->nFaces[0]->faceIdentity==faceNum)
1655  vec1Face=e1->nFaces[0];
1656  else if (e1->nFaces[1]->faceIdentity==faceNum)
1657  vec1Face=e1->nFaces[1];
1658  else
1659  gsDebug<<"selected Edge has no valid neighboring face"<<"\n";
1660  if (e2->nFaces[0]->faceIdentity==faceNum)
1661  vec2Face=e2->nFaces[0];
1662  else if (e2->nFaces[1]->faceIdentity==faceNum)
1663  vec2Face=e2->nFaces[1];
1664  else
1665  gsDebug<<"selected Edge has no valid neighboring face"<<"\n";
1666  gsVector3d<T> normal1=vec1Face->orthogonalVector();
1667  gsVector3d<T> normal2=vec2Face->orthogonalVector();
1668  gsVector3d<T> normal=(normal1+normal2)/2;
1669  T angle=conditionedAngle(vec1,vec2,normal);
1670 
1671  return angle;
1672 
1673 }
1674 
1675 
1676 template<class T>
1677 T gsTriMeshToSolid<T>::calcBdryLength(std::vector<VertexHandle > vec)
1678 {
1679  T length=0;
1680  for (size_t i=0;i<vec.size()-1;i++)
1681  length+=calcDist(vec[i],vec[i+1]);
1682  length+=calcDist(vec[0],vec.back());
1683  return length;
1684 }
1685 
1686 
1687 template<class T>
1688 gsVertex<T> gsTriMeshToSolid<T>::getMassP(std::vector<VertexHandle > vec)
1689 {
1690  T x=0,y=0,z=0;
1691  for (size_t i=0;i<vec.size();i++)
1692  {
1693  x+=vec[i]->x();
1694  y+=vec[i]->y();
1695  z+=vec[i]->z();
1696  }
1697  x/=vec.size();
1698  y/=vec.size();
1699  z/=vec.size();
1700  return gsVertex<T>(x,y,z);
1701 }
1702 
1703 
1704 template<class T>
1706 {
1707  return (*v1 - *v2).norm();
1708 }
1709 
1710 
1711 template<class T>
1712 std::vector<bool> gsTriMeshToSolid<T>::isCorner(std::vector<VertexHandle > const & vertexVec3d)
1713 {
1714  std::vector<bool> isCorner;
1715  for(size_t i=0;i<vertexVec3d.size();i++)
1716  {
1717  if(vertexVec3d[i]->numEdges>2)
1718  isCorner.push_back(1);
1719  else
1720  isCorner.push_back(0);
1721  }
1722  return isCorner;
1723 }
1724 
1725 
1726 template<class T>
1728 {
1729  gsMatrix<T> tcp(2, 2);
1730  tcp << v1.x(), v1.y(), v2.x(), v2.y();
1731  gsBSpline<T> * tcurve = new gsBSpline<T>( 0, 1, 0, 1, give(tcp) );
1732  return tcurve;
1733 }
1734 
1735 
1736 template<class T>
1738 {
1739  gsMatrix<T> tcp(3, 2);
1740  tcp << v1.x(), v1.y(), v2.x(), v2.y(), v3.x(), v3.y();
1741  gsBSpline<T> * tcurve = new gsBSpline<T>( 0, 1, 0, 2, give(tcp) );
1742  return tcurve;
1743 }
1744 
1745 
1746 template<class T>
1748 {
1749  return gsVertex<T>((v1[0]+v2[0])/(T)(2),
1750  (v1[1]+v2[1])/(T)(2),
1751  (v1[2]+v2[2])/(T)(2));
1752 }
1753 
1754 
1755 template <class T>
1756 void gsTriMeshToSolid<T>::readEdges( std::string const & fn, std::vector<gsEdge <T> > & edges )
1757 {
1758  std::string line;
1759  std::ifstream myfile (fn.c_str());
1760  if (myfile.is_open())
1761  {
1762  int count=1;
1763  T x1=0,x2=0,y1=0,y2=0,z1=0,z2=0;
1764  while(myfile >> line)
1765  {
1766 
1767  if(count==1)
1768  x1 = atof(line.c_str());
1769  else if(count==2)
1770  y1 = atof(line.c_str());
1771  else if(count==3)
1772  z1 = atof(line.c_str());
1773  else if(count==4)
1774  x2 = atof(line.c_str());
1775  else if(count==5)
1776  y2 = atof(line.c_str());
1777  else if(count==6)
1778  {
1779  z2 = atof(line.c_str());
1780  gsVertex<T> * v1 = new gsVertex<T>(x1,y1,z1);
1781  gsVertex<T> * v2 = new gsVertex<T>(x2,y2,z2);
1782 
1783  if(Xless<T>(v1,v2))std::swap(v1,v2);
1784  gsEdge<T> featureEdge(v1,v2);
1785  edges.push_back(featureEdge);
1786 
1787  count-=6;
1788  }
1789  count++;
1790  }
1791 
1792  myfile.close();
1793  }
1794 }
1795 
1796 
1797 template <class T>
1799 {
1800  T d1=calcDist(f1->vertices[0],f1->vertices[1]);
1801  T d2=calcDist(f1->vertices[0],f1->vertices[2]);
1802  T d3=calcDist(f1->vertices[1],f1->vertices[2]);
1803  //p=perimeter/2
1804  T p=(d1+d2+d3)/(T)(2);
1805  T area=math::sqrt(p*(p-d1)*(p-d2)*(p-d3));
1806  return area;
1807 }
1808 
1809 }
static T calcBdryLength(std::vector< VertexHandle > vec)
Adds up the lengths between 2 neighboring vertices of a vector of vertices.
Definition: gsTriMeshToSolid.hpp:1677
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix...
Definition: gsSparseMatrix.h:33
A fixed-size, statically allocated 3D vector.
Definition: gsVector.h:218
Class for a trim surface.
Definition: gsTrimSurface.h:33
static T calcArea(FaceHandle f1)
using Heron&#39;s Formula for the area of a triangle.
Definition: gsTriMeshToSolid.hpp:1798
T distance(gsMatrix< T > const &A, gsMatrix< T > const &B, index_t i=0, index_t j=0, bool cols=false)
compute a distance between the point number in the set and the point number &lt;j&gt; in the set ; by def...
#define gsDebug
Definition: gsDebug.h:61
memory::unique_ptr< gsMesh< T > > toMesh(int npoints=50) const
Return a triangulation of the planar domain.
Definition: gsPlanarDomain.hpp:248
void setSharpEdges(std::vector< gsEdge< T > > &featEdges, int useFeatures)
Sets sharp edges according to the value of useFeatures.
Definition: gsTriMeshToSolid.hpp:185
Provides interface of gsTrimSurface class. Represents a trimmed surface (= spline &quot;master surface&quot; in...
S give(S &x)
Definition: gsMemory.h:266
This class is derived from std::vector, and adds sort tracking.
Definition: gsSortedVector.h:109
gsBSpline< T > * calcTCurve(Vertex v1, Vertex v2)
calculates a B-spline of degree one from 2 vertices.
Definition: gsTriMeshToSolid.hpp:1727
static bool approxEqual(const gsEdge< T > &e1, const gsEdge< T > &e2)
checks if two edges are very close to each other.
Definition: gsTriMeshToSolid.hpp:1597
void getPatchData(T angle, T innerAngle, T patchAreaWeight, T mergeSmallPatches, std::vector< std::vector< VertexHandle > > &iPoints, std::vector< std::vector< VertexHandle > > &oPoints, std::vector< std::vector< std::vector< VertexHandle > > > &innerBdrys, std::vector< std::vector< Vertex > > &innerBdrysMassP, std::vector< std::vector< bool > > &oPointsConvexFlag, std::string filenameFeatures, int useFeatures)
Computes data describing the patch structure of the mesh. Combines getFeatures and getFaces...
Definition: gsTriMeshToSolid.hpp:1405
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
static T calcWeight(VertexHandle v1, VertexHandle v2, std::set< VertexHandle > const &vertexFaceSet)
calculates a weight between 2 vertices used in Floater&#39;s algorithm.
Definition: gsTriMeshToSolid.hpp:1531
A B-spline function of one argument, with arbitrary target dimension.
Definition: gsBSpline.h:50
Class Representing a triangle mesh with 3D vertices.
Definition: gsMesh.h:31
void getFaces(std::vector< std::vector< VertexHandle > > &iPoints, std::vector< std::vector< VertexHandle > > &oPoints, std::vector< std::vector< std::vector< VertexHandle > > > &innerBdrys, std::vector< std::vector< Vertex > > &innerBdrysMassP, std::vector< std::vector< bool > > &oPointsConvexFlag)
Computes data describing the patch structure of the mesh.
Definition: gsTriMeshToSolid.hpp:311
#define gsWarn
Definition: gsDebug.h:50
static Vertex giveMidpoint(Vertex v1, Vertex v2)
calculates the midpoint of two vertices.
Definition: gsTriMeshToSolid.hpp:1747
void flip1(T minu=0, T maxu=1)
flip a curve loop in the u direction
Definition: gsCurveLoop.hpp:608
void addHeVertex(scalar_t const &x, scalar_t const &y, scalar_t const &z=0)
add coords to gsHeVertex, not yet pointers to HEs
Definition: gsSolid.hpp:51
static std::vector< bool > isCorner(std::vector< VertexHandle > const &vertexVec3d)
checks whether vertices are corners.
Definition: gsTriMeshToSolid.hpp:1712
T x() const
Definition: gsVertex.h:108
void addVolume(gsVolumeHandle vol)
add a volume using its handle
Definition: gsSolid.h:167
T conditionedAngle(gsVector3d< T > vec1, gsVector3d< T > vec2)
Angle between two vector: 0 &lt;= angle &lt;= pi.
Definition: gsModelingUtils.hpp:165
void toSolid(gsSolid< T > &sl, std::vector< std::vector< VertexHandle > > &iPoints, std::vector< std::vector< VertexHandle > > &oPoints, std::vector< std::vector< std::vector< VertexHandle > > > &innerBdrys, std::vector< std::vector< Vertex > > &innerBdrysMassP, std::vector< std::vector< bool > > &oPointsConvexFlag, std::vector< gsMesh< T > * > &paraMeshes, std::vector< gsMesh< T > * > &fitMeshes, std::vector< gsMesh< T > * > &patchMeshes, int kvOuterPoints, int kvAdditionalInnerPoints, bool plot, int meshPoints, bool moreInner=true, T wE=5, T wI=1, int closeBoundary=0, bool noSmooth=false)
Parametrized a number of patches given by iPoints, oPoints, innerBdrys, innerBdrysMassP and oPointsCo...
Definition: gsTriMeshToSolid.hpp:566
gsTensorBSpline< 2, T >::Ptr gsInterpolateSurface(const gsMatrix< T > &exactPoints, const gsMatrix< T > &exactValues, const gsMatrix< T > &appxPointsEdges, const gsMatrix< T > &appxValuesEdges, const gsMatrix< T > &appxPointsInt, const gsMatrix< T > &appxValuesInt, const gsMatrix< T > &appxNormalPoints, const gsMatrix< T > &appxNormals, T wEdge, T wInt, T wNormal, T wReg, const gsKnotVector< T > &kv1, const gsKnotVector< T > &kv2, bool force_normal)
Definition: gsModelingUtils.hpp:504
void setHeMate()
Assigning mates for each HE.
Definition: gsSolid.hpp:320
gsSolidHalfFaceHandle addFace(std::vector< gsSolidHeVertexHandle > V)
Definition: gsSolid.hpp:82
Represents a B-spline curve/function with one parameter.
Class representing a Planar domain with an outer boundary and a number of holes.
Definition: gsPlanarDomain.h:43
void readEdges(std::string const &fn, std::vector< gsEdge< T > > &edges)
reads a text file consisting of lines of 6 values, each line representing an edge.
Definition: gsTriMeshToSolid.hpp:1756
T y() const
Definition: gsVertex.h:110
bool initFrom3DByAngles(const std::vector< gsVector3d< T > * > points3D, const std::vector< bool > isConvex, T margin)
Definition: gsCurveLoop.hpp:483
Utility functions required by gsModeling classes.
void divideAndMergePatches(T innerAngle, T patchAreaWeight, T mergeSmallPatches)
Improve surface segmentation by using more complex rules.
Definition: gsTriMeshToSolid.hpp:239
#define GISMO_UNUSED(x)
Definition: gsDebug.h:112
static T calcDist(VertexHandle v1, VertexHandle v2)
calculates the distance between 2 vertices.
Definition: gsTriMeshToSolid.hpp:1705
Class for representing a solid made up of vertices, edges, faces, and volumes.
Definition: gsSolid.h:32
void initFromIsConvex(const std::vector< bool > isConvex, T margin)
Initialize a curve loop from a list of bools indicating whether the corners are convex or not...
Definition: gsCurveLoop.hpp:514
Class for representing a knot vector.
Definition: gsKnotVector.h:79
static gsVertex< T > getMassP(std::vector< VertexHandle > vec)
calculates the mass point of a vector of vertices.
Definition: gsTriMeshToSolid.hpp:1688
void storeNeighboringFaces()
Store each edge&#39;s neighboring faces.
Definition: gsTriMeshToSolid.hpp:222
A closed loop given by a collection of curves.
Definition: gsCurveLoop.h:36
static int normalMult(gsVector3d< T > globalNormal, std::vector< FaceHandle > &face, int bigFaceIdx)
Definition: gsTriMeshToSolid.hpp:1562
gsCurveLoop< T > * calculateLoop(std::vector< Vertex > outerPoints, std::vector< bool > const &isCorner, bool noSmooth=false)
calculates a curve loop consisting of B-spline curves of degree one and two from a vector of vertices...
Definition: gsTriMeshToSolid.hpp:1444
void getFeatures(T angleGrad, bool &bWarnNonManifold, bool &bWarnBorders)
generates edges for a mesh consisting of vertices and faces. Determines if these edges are sharp...
Definition: gsTriMeshToSolid.hpp:72
memory::shared_ptr< gsTensorBSpline > Ptr
Shared pointer for gsTensorBSpline.
Definition: gsTensorBSpline.h:59
Interface for gsCurveLoop class, representing a loop of curves, in anticlockwise order.
void calcPatchNumbers()
Each face obtains a patch number, faces of the same number belong to the same patch.
Definition: gsTriMeshToSolid.hpp:27
Provides declaration of gsPlanarDomain class. The outer boundary (m_loops[0]) is a loop of curves...
T z() const
Definition: gsVertex.h:112
gsVertex class that represents a 3D vertex for a gsMesh.
Definition: gsVertex.h:26
Provides declaration of gsSolid class, a boundary-represented solid.
static T calcAngle(EdgeHandle e1, EdgeHandle e2, int faceNum)
calculates the conditioned angle between 2 edges.
Definition: gsTriMeshToSolid.hpp:1617