G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsTriMeshToSolid.hpp
Go to the documentation of this file.
1
18 #include <gsModeling/gsSolid.h>
19 #include <gsNurbs/gsBSpline.h>
20
21#include <fstream>
22
23namespace gismo
24{
25
26template <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
71template <class T>
72void 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
184template <class T>
185void 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
221template <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
238template <class T>
239void 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
310template <class T>
311void 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
565template <class T>
566void 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
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
1404template <class T>
1405void 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
1443template <class T>
1444gsCurveLoop<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
1530template<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
1561template <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
1596template<class T>
1597bool 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
1616template <class T>
1617T 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
1676template<class T>
1677T 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
1687template<class T>
1688gsVertex<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
1704template<class T>
1706{
1707 return (*v1 - *v2).norm();
1708}
1709
1710
1711template<class T>
1712std::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
1726template<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
1736template<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
1746template<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
1755template <class T>
1756void 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
1797template <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}
A B-spline function of one argument, with arbitrary target dimension.
Definition gsBSpline.h:51
A closed loop given by a collection of curves.
Definition gsCurveLoop.h:37
void flip1(T minu=0, T maxu=1)
flip a curve loop in the u direction
Definition gsCurveLoop.hpp:608
bool initFrom3DByAngles(const std::vector< gsVector3d< T > * > points3D, const std::vector< bool > isConvex, T margin)
Definition gsCurveLoop.hpp:483
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:80
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
Class Representing a triangle mesh with 3D vertices.
Definition gsMesh.h:32
gsMesh & cleanMesh()
reorders the vertices of all faces of an .stl mesh, such that only 1 vertex is used instead of #(adja...
Definition gsMesh.hpp:250
Class representing a Planar domain with an outer boundary and a number of holes.
Definition gsPlanarDomain.h:44
Class for representing a solid made up of vertices, edges, faces, and volumes.
Definition gsSolid.h:33
void addVolume(gsVolumeHandle vol)
add a volume using its handle
Definition gsSolid.h:167
gsSolidHalfFaceHandle addFace(std::vector< gsSolidHeVertexHandle > V)
Definition gsSolid.hpp:82
void setHeMate()
Assigning mates for each HE
Definition gsSolid.hpp:320
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
This class is derived from std::vector, and adds sort tracking.
Definition gsSortedVector.h:110
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix.
Definition gsSparseMatrix.h:34
memory::shared_ptr< gsTensorBSpline > Ptr
Shared pointer for gsTensorBSpline.
Definition gsTensorBSpline.h:59
static gsVertex< T > getMassP(std::vector< VertexHandle > vec)
calculates the mass point of a vector of vertices.
Definition gsTriMeshToSolid.hpp:1688
void setSharpEdges(std::vector< gsEdge< T > > &featEdges, int useFeatures)
Sets sharp edges according to the value of useFeatures.
Definition gsTriMeshToSolid.hpp:185
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
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
static T calcBdryLength(std::vector< VertexHandle > vec)
Adds up the lengths between 2 neighboring vertices of a vector of vertices.
Definition gsTriMeshToSolid.hpp:1677
static std::vector< bool > isCorner(std::vector< VertexHandle > const &vertexVec3d)
checks whether vertices are corners.
Definition gsTriMeshToSolid.hpp:1712
gsBSpline< T > * calcTCurve(Vertex v1, Vertex v2)
calculates a B-spline of degree one from 2 vertices.
Definition gsTriMeshToSolid.hpp:1727
void calcPatchNumbers()
Each face obtains a patch number, faces of the same number belong to the same patch.
Definition gsTriMeshToSolid.hpp:27
static Vertex giveMidpoint(Vertex v1, Vertex v2)
calculates the midpoint of two vertices.
Definition gsTriMeshToSolid.hpp:1747
static T calcWeight(VertexHandle v1, VertexHandle v2, std::set< VertexHandle > const &vertexFaceSet)
calculates a weight between 2 vertices used in Floater's algorithm.
Definition gsTriMeshToSolid.hpp:1531
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
static T calcDist(VertexHandle v1, VertexHandle v2)
calculates the distance between 2 vertices.
Definition gsTriMeshToSolid.hpp:1705
static T calcArea(FaceHandle f1)
using Heron's Formula for the area of a triangle.
Definition gsTriMeshToSolid.hpp:1798
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
static int normalMult(gsVector3d< T > globalNormal, std::vector< FaceHandle > &face, int bigFaceIdx)
Definition gsTriMeshToSolid.hpp:1562
static T calcAngle(EdgeHandle e1, EdgeHandle e2, int faceNum)
calculates the conditioned angle between 2 edges.
Definition gsTriMeshToSolid.hpp:1617
void divideAndMergePatches(T innerAngle, T patchAreaWeight, T mergeSmallPatches)
Improve surface segmentation by using more complex rules.
Definition gsTriMeshToSolid.hpp:239
void storeNeighboringFaces()
Store each edge's neighboring faces.
Definition gsTriMeshToSolid.hpp:222
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
Class for a trim surface.
Definition gsTrimSurface.h:34
memory::unique_ptr< gsMesh< T > > toMesh(int npoints=50) const
Return a triangulation of the trimmed surface.
Definition gsTrimSurface.hpp:236
A fixed-size, statically allocated 3D vector.
Definition gsVector.h:219
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
gsVertex class that represents a 3D vertex for a gsMesh.
Definition gsVertex.h:27
T x() const
Definition gsVertex.h:120
T z() const
Definition gsVertex.h:124
T y() const
Definition gsVertex.h:122
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
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
Represents a B-spline curve/function with one parameter.
Interface for gsCurveLoop class, representing a loop of curves, in anticlockwise order.
#define gsDebug
Definition gsDebug.h:61
#define gsWarn
Definition gsDebug.h:50
#define GISMO_UNUSED(x)
Definition gsDebug.h:112
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Utility functions required by gsModeling classes.
Provides declaration of gsPlanarDomain class. The outer boundary (m_loops[0]) is a loop of curves,...
Provides declaration of gsSolid class, a boundary-represented solid.
Provides interface of gsTrimSurface class. Represents a trimmed surface (= spline "master surface" in...
The G+Smo namespace, containing all definitions for the library.
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
T conditionedAngle(gsVector3d< T > vec1, gsVector3d< T > vec2)
Angle between two vector: 0 <= angle <= pi.
Definition gsModelingUtils.hpp:165
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 <j> in the set ; by def...
S give(S &x)
Definition gsMemory.h:266