183 int faceVerts = V.size();
184 assert(faceVerts >= 3);
189 int minVert = faceVerts - 1;
190 for(
int i = 0; i < faceVerts - 1; i++)
192 if(V[i]->coords(0) < V[minVert]->coords(0) ||
193 (V[i]->coords(0) <= V[minVert]->coords(0) && V[i]->coords(1) < V[minVert]->coords(1)))
199 gsVector3d<T> prevVector = V[(minVert + faceVerts - 1) % faceVerts]->coords - V[minVert]->coords;
202 int nextVertex = minVert;
203 while(normal.squaredNorm() == 0)
205 nextVertex = (nextVertex + 1) % faceVerts;
206 assert(nextVertex != minVert);
207 normal = (V[nextVertex]->coords - V[minVert]->coords).cross(prevVector);
210 for(
int i = 3; i < faceVerts; i++)
212 assert((V[i]->coords - V[0]->coords).dot(normal) == 0);
214 T normalCoord = normal.dot(V[0]->coords);
225 a1 = a1.cross(normal);
226 a2 = a2.cross(normal);
228 if(a1.squaredNorm() > a2.squaredNorm())
237 b2 = normal.cross(b1);
248 for(
int i = 0; i < faceVerts; i++)
251 x = b1.dot(V[i]->coords);
252 y = b2.dot(V[i]->coords);
257 DomCor(faceVerts, 0) = DomCor(0, 0);
258 DomCor(faceVerts, 1) = DomCor(0, 1);
261 T minx = DomCor.col(0).minCoeff();
262 T maxx = DomCor.col(0).maxCoeff();
263 T miny = DomCor.col(1).minCoeff();
264 T maxy = DomCor.col(1).maxCoeff();
265 T rangex = maxx - minx, rangey = maxy - miny;
266 T midx = (minx + maxx) / (T)(2), midy = (miny + maxy) / (T)(2);
267 T halfMaxRange = std::max(rangex, rangey) * (margin * (T)(2) + (T)(1)) / (T)(2);
268 minx -= rangex * margin;
269 maxx += rangex * margin;
270 miny -= rangey * margin;
271 maxy += rangey * margin;
280 for(
int i = 0; i < faceVerts; i++)
283 tcp << DomCor(i, 0), DomCor(i, 1), DomCor(i + 1, 0), DomCor(i + 1, 1);
285 tloop->insertCurve(tcurve);
301 for(
int xi = 0; xi < 3; xi++)
303 pcp(0, xi) = normal[xi] * normalCoord + (midx - halfMaxRange) * b1[xi] + (midy - halfMaxRange) * b2[xi];
304 pcp(1, xi) = normal[xi] * normalCoord + (midx + halfMaxRange) * b1[xi] + (midy - halfMaxRange) * b2[xi];
305 pcp(2, xi) = normal[xi] * normalCoord + (midx - halfMaxRange) * b1[xi] + (midy + halfMaxRange) * b2[xi];
306 pcp(3, xi) = normal[xi] * normalCoord + (midx + halfMaxRange) * b1[xi] + (midy + halfMaxRange) * b2[xi];
315 return addFace(V, ts);
375 gsSolidHalfFaceHandle f,
376 gsSolidHeVertexHandle startVertex, gsSolidHeVertexHandle endVertex,
gsBSpline<T> *domainSpline)
380 int numEdges = f->surf->domain().outer().size();
382 gsSolidHalfEdgeHandle nextEdge = endVertex->getHalfEdgeOnFace(f,
false);
383 gsSolidHalfEdgeHandle matesPrev = nextEdge->prev;
384 int nextEdgeIdx = f->indexOfEdge(nextEdge);
386 gsSolidHalfEdgeHandle prevEdge = startVertex->getHalfEdgeOnFace(f,
true);
387 gsSolidHalfEdgeHandle matesNext = prevEdge->next;
388 int prevEdgeIdx = f->indexOfEdge(prevEdge);
390 gsSolidHalfEdgeHandle newHE = this->makeSolidHalfEdge(startVertex, f);
392 newHE->setId(numHalfEdges++);
395 newHE->prev = prevEdge;
396 newHE->next = nextEdge;
397 prevEdge->next = newHE;
398 nextEdge->prev = newHE;
400 gsSolidHalfEdgeHandle mate = this->makeSolidHalfEdge(endVertex, f);
403 mate->setId(numHalfEdges++);
406 mate->prev = matesPrev;
407 mate->next = matesNext;
408 matesPrev->next = mate;
409 matesNext->prev = mate;
411 std::vector<gsSolidHalfEdgeHandle> newFaceBoundary;
412 newFaceBoundary.push_back(mate);
413 gsSolidHalfEdgeHandle tempEdge;
414 for(tempEdge = matesNext; tempEdge != mate; tempEdge = tempEdge->next)
416 newFaceBoundary.push_back(tempEdge);
420 std::vector<T> origKnots = domainSpline->
knots();
421 std::vector<T> mateKnots;
422 mateKnots.reserve( origKnots.size() );
423 T flipPoint = (*origKnots.begin()) + (*origKnots.rbegin());
424 for(
int i = origKnots.size() - 1; i >= 0; i--)
426 mateKnots.push_back(flipPoint - origKnots[i]);
433 typename gsPlanarDomain<T>::uPtr newDomain =
434 f->surf->domain().split((prevEdgeIdx + 1) % numEdges, nextEdgeIdx, domainSpline, reverseSpline);
435 if(prevEdgeIdx > nextEdgeIdx)
440 f->loop[0] = nextEdge;
449 edge.push_back( newHE );
450 edge.push_back( mate );
452 gsSolidHalfFaceHandle newFace =
new gsSolidHalfFace<T>();
453 newFace->surf = newTS;
454 newFace->setBoundary( newFaceBoundary );
455 face.push_back(newFace);
456 newFace->setId(numHalfFaces++);
457 newFace->vol = f->vol;
458 newFace->vol->face.push_back(newFace);
464 tempEdge->face = newFace;
465 tempEdge = tempEdge->next;
466 }
while(tempEdge != mate);
494 gsVolumeHandle newVol =
new gsVolumeBlock<T>;
495 volume.push_back(newVol);
496 newVol->setId(numVolumes++);
500 std::queue<gsSolidHalfFaceHandle> unprocessed;
501 unprocessed.push(startingFace);
502 std::set<gsSolidHalfFaceHandle> seen;
503 seen.insert(startingFace);
505 while(!unprocessed.empty())
508 gsSolidHalfFaceHandle nextFace = unprocessed.front();
511 nextFace->vol = newVol;
512 newVol->face.push_back(nextFace);
513 size_t numLoops = nextFace->loop.size();
515 for(
size_t i = 0; i < numLoops; i++)
517 gsSolidHalfEdgeHandle firstEdge = nextFace->loop[i];
518 gsSolidHalfEdgeHandle nextEdge = firstEdge;
521 gsSolidHalfFaceHandle neighbFace = nextEdge->mate->face;
522 if(seen.find(neighbFace) == seen.end())
524 unprocessed.push(neighbFace);
525 seen.insert(neighbFace);
527 nextEdge = nextEdge->next;
528 }
while(nextEdge != firstEdge);
533 unsigned foundFaces = 0;
534 GISMO_ASSERT(numVolumes == volume.size(),
"Number of volumes does not match");
535 for(
size_t idxV = 0; idxV < numVolumes; idxV++)
538 size_t numF = volume[idxV]->face.size();
539 for(
size_t inF = 0; inF < numF; inF++)
541 if(volume[idxV]->face[inF]->vol == volume[idxV])
543 volume[idxV]->face[outF] = volume[idxV]->face[inF];
548 volume[idxV]->face.resize(outF);
550 GISMO_ASSERT(foundFaces == face.size() && foundFaces == numHalfFaces,
551 "Failed to assign a volume for all faces.");
604 GISMO_ASSERT(verts.size() >= 2,
"Unexpected number of vertices in new face");
607 std::vector<gsSolidHeVertexHandle> reorderedVerts;
608 reorderedVerts.push_back(verts[verts.size() - 1]);
609 for(
size_t iV = 0; iV < verts.size() - 1; iV++)
611 reorderedVerts.push_back(verts[iV]);
614 surf->cleanEndpoints(0.0000001);
618 size_t numLoops = surf->domain().numLoops();
619 for(
size_t loopNum = 0; loopNum < numLoops; loopNum++)
621 size_t numCurves = surf->domain().loop(loopNum).size();
622 for(
size_t curveNum = 0; curveNum < numCurves; curveNum++)
624 gsMatrix<T> surfCoord = surf->vertexCoord(loopNum, curveNum);
625 GISMO_ASSERT((surfCoord - reorderedVerts[curveNum]->coords).norm() < 0.0001,
"Vertices in surface do not match vertex coordinates");
632 gsMatrix<T> &surfRevCoefs = surfReverse->getTP()->coefs();
633 MasterSurface *genGeom =
dynamic_cast<MasterSurface *
>(surfReverse->getTP().get());
634 GISMO_ASSERT(genGeom != NULL,
"This procedure requires a gsGenericGeometry");
635 gsMatrix<T> revSupp = surfReverse->getTP()->support();
636 GISMO_ASSERT(revSupp.cols() == 2,
"Unexpected support");
639 testPt << 0.75 * revSupp(0, 0) + 0.25 * revSupp(0, 1), 0.75 * revSupp(0, 0) + 0.25 * revSupp(0, 1), 0.25 * revSupp(0, 0) + 0.75 * revSupp(0, 1), 0.25 * revSupp(0, 0) + 0.75 * revSupp(0, 1),
640 0.75 * revSupp(1, 0) + 0.25 * revSupp(1, 1), 0.25 * revSupp(1, 0) + 0.75 * revSupp(1, 1), 0.75 * revSupp(1, 0) + 0.25 * revSupp(1, 1), 0.25 * revSupp(1, 0) + 0.75 * revSupp(1, 1);
642 genGeom->eval_into(testPt, testVal1);
644 unsigned totalCPs = surfRevCoefs.rows();
645 unsigned dim = surfRevCoefs.cols();
646 unsigned blockSize = genGeom->basis().component(0).size();
647 for(
unsigned blockStart = 0; blockStart < totalCPs; blockStart += blockSize)
649 surfRevCoefs.block(blockStart, 0, blockSize, dim) =
650 surfRevCoefs.block(blockStart, 0, blockSize, dim).colwise().reverse().eval();
655 testPt << 0.25 * revSupp(0, 0) + 0.75 * revSupp(0, 1), 0.25 * revSupp(0, 0) + 0.75 * revSupp(0, 1), 0.75 * revSupp(0, 0) + 0.25 * revSupp(0, 1), 0.75 * revSupp(0, 0) + 0.25 * revSupp(0, 1),
656 0.75 * revSupp(1, 0) + 0.25 * revSupp(1, 1), 0.25 * revSupp(1, 0) + 0.75 * revSupp(1, 1), 0.75 * revSupp(1, 0) + 0.25 * revSupp(1, 1), 0.25 * revSupp(1, 0) + 0.75 * revSupp(1, 1);
658 genGeom->eval_into(testPt, testVal2);
660 gsMatrix<T> testRevCoefs = surfReverse->getTP()->coefs();
661 GISMO_ASSERT((testVal2 - testVal1).norm() < 0.0001,
"Surface was not correctly reversed");
666 numLoops = surfReverse->domain().numLoops();
667 for(
size_t loopNum = 0; loopNum < numLoops; loopNum++)
669 gsCurveLoop<T> & revCurveLoop = surfReverse->domain().loop(loopNum);
670 size_t numCurves = revCurveLoop.size();
671 for(
size_t curveNum = 0; curveNum < numCurves; curveNum++)
675 curveCoefs = curveCoefs.colwise().reverse().eval();
676 size_t rows = curveCoefs.rows();
677 for(
size_t cpIdx = 0; cpIdx < rows; cpIdx++)
679 curveCoefs(cpIdx, 0) = revSupp(0, 0) + revSupp(0, 1) - curveCoefs(cpIdx, 0);
684 std::reverse( revCurveLoop.curves().begin(), revCurveLoop.curves().end() );
688 for(
size_t loopNum = 0; loopNum < numLoops; loopNum++)
690 const gsCurveLoop<T> & revCurveLoop = surfReverse->domain().loop(loopNum);
691 size_t numCurves = revCurveLoop.size();
692 for(
size_t curveNum = 0; curveNum < numCurves; curveNum++)
695 const gsGeometry<T> & thisCurve = revCurveLoop.curve(curveNum);
696 const gsGeometry<T> & nextCurve = revCurveLoop.curve((curveNum + 1) % numCurves);
701 GISMO_ASSERT((thisEndPt - nextStartPt).norm() < 0.0001,
"Invalid curve loop");
703 gsMatrix<T> thisCoord = surfReverse->vertexCoord(loopNum, curveNum);
704 gsMatrix<T> otherCoord = surf->vertexCoord(loopNum, (numCurves - curveNum) % numCurves);
705 GISMO_ASSERT((otherCoord - thisCoord).norm() < 0.0001,
"Mate faces do not have matching vertices");
706 GISMO_ASSERT((otherCoord - reorderedVerts[(numCurves - curveNum) % numCurves]->coords).norm() < 0.0001,
"Vertices in surface do not match vertex coordinates");
711 gsSolidHalfEdgeHandle startEdge = reorderedVerts[0]->getHalfEdge(reorderedVerts[1]);
713 std::vector<gsSolidHeVertexHandle> newVerts, newVertsReverse;
714 for(
typename std::vector<gsSolidHeVertexHandle>::const_iterator iter = reorderedVerts.begin(); iter != reorderedVerts.end(); iter++)
716 addHeVertex((*iter)->coords(0), (*iter)->coords(1), (*iter)->coords(2));
717 newVerts.push_back(vertex[numVertices - 1]);
720 newVertsReverse.push_back(newVerts[0]);
721 for(
int i = newVerts.size() - 1; i > 0; i--) newVertsReverse.push_back(newVerts[i]);
723 gsSolidHalfFaceHandle frontFace = addFace(reorderedVerts, surf);
725 gsSolidHalfFaceHandle backFace = addFace(newVertsReverse, surfReverse);
726 backFace->vol = NULL;
728 frontFace->mate = backFace;
729 backFace->mate = frontFace;
732 size_t vertNum, numVerts = reorderedVerts.size();
733 for(vertNum = 0; vertNum < numVerts; vertNum++)
735 gsSolidHeVertex<T> *thisVert = reorderedVerts[vertNum];
736 gsSolidHeVertex<T> *nextVert = reorderedVerts[(vertNum + 1) % numVerts];
737 while(thisVert->hed->next->source != nextVert)
739 thisVert->hed = thisVert->hed->mate->next;
740 GISMO_ASSERT(thisVert->hed->source == thisVert,
"Inconsistent solid graph");
742 thisVert->hed = thisVert->hed->mate->next;
743 GISMO_ASSERT(thisVert->hed->source == thisVert,
"Inconsistent solid graph");
746 gsSolidHalfEdge<T> *he = startEdge;
748 gsSolidHalfEdgeHandle newFrontFaceEdge = frontFace->loop[0];
749 while(newFrontFaceEdge->source != reorderedVerts[0]) newFrontFaceEdge = newFrontFaceEdge->next;
750 gsSolidHalfEdgeHandle newBackFaceEdge = backFace->loop[0];
751 while(newBackFaceEdge->source != newVerts[1]) newBackFaceEdge = newBackFaceEdge->next;
755 he->mate->mate = newFrontFaceEdge;
756 newFrontFaceEdge->mate = he->mate;
758 he->mate = newBackFaceEdge;
759 newBackFaceEdge->mate = he;
762 GISMO_ASSERT(backFace->vol == NULL || backFace->vol == he->face->vol,
"Inconsistent solid graph");
763 backFace->vol = he->face->vol;
765 GISMO_ASSERT(newFrontFaceEdge->source == reorderedVerts[vertNum],
"Inconsistent solid graph");
766 GISMO_ASSERT(newBackFaceEdge->source == newVerts[(vertNum + 1) % numVerts],
"Inconsistent solid graph");
770 newFrontFaceEdge = newFrontFaceEdge->next;
771 newBackFaceEdge = newBackFaceEdge->prev;
773 gsSolidHeVertexHandle nextVert = reorderedVerts[(vertNum + 1) % numVerts];
778 GISMO_ASSERT(he->source->hed->source == he->source,
"Inconsistent solid graph");
779 if(he->source->hed == he) he->source->hed = newFrontFaceEdge;
780 he->source = newVerts[vertNum % numVerts];
781 if(he->next->source == nextVert || he == startEdge)
break;
782 GISMO_ASSERT(he->source->hed->source == he->source,
"Inconsistent solid graph");
783 GISMO_ASSERT(he->prev->target() == he->source,
"Inconsistent solid graph");
786 }
while(he != startEdge);
789 GISMO_ASSERT(backFace->vol != NULL,
"Could not find the volume for mate face");
790 backFace->vol->face.push_back(backFace);
793 newVolume(frontFace);
799 gsSolidHalfEdge<T>* he0;
800 he0 = frontFace->loop[0];
802 for (
size_t i=0;i<this->nHalfEdges();i++)
804 he->is_convex =
true;
805 he->mate->is_convex =
true;
806 if (he->target()==he0->source)
break;
810 he0 = frontFace->mate->loop[0];
812 for (
size_t i=0;i<this->nHalfEdges();i++)
814 he->is_convex =
true;
815 he->mate->is_convex =
true;
816 if (he->target()==he0->source)
break;
869 gsSolidHalfEdgeHandle hem = he->mate;
870 gsSolidHalfFaceHandle face0,face1;
872 face1 = he->mate->face;
873 size_t nFace = this->nHalfFaces();
874 bool convex = he->is_convex;
875 int heLoopN = he->loopN();
876 int hemLoopN = hem->loopN();
878 size_t he_tCurveID = face0->indexOfEdge(he);
879 size_t hem_tCurveID = face1->indexOfEdge(hem);
880 gsMatrix<T> mid0 = face0->surf->splitCurve(he->loopN(), he_tCurveID);
882 face0->surf->getTP()->eval_into(mid0.transpose(), space0);
884 T nearestParam = face1->surf->nearestPoint(0, hem_tCurveID, 10, 10, space0);
885 gsMatrix<T> mid1 = face1->surf->splitCurve(hem->loopN(), hem_tCurveID, nearestParam);
887 face1->surf->getTP()->eval_into(mid1.transpose(), space1);
892 gsSolidHeVertexHandle s,n,t;
894 n =
new gsSolidHeVertex<T>(
895 0.5 * (space0(0, 0) + space1(0, 0)),
896 0.5 * (space0(1, 0) + space1(1, 0)),
897 0.5 * (space0(2, 0) + space1(2, 0)),
900 (this->vertex).push_back(n);
905 gsSolidHalfEdgeHandle sn =
new gsSolidHalfEdge<T>(s,face0,nFace,convex,heLoopN);
906 gsSolidHalfEdgeHandle nt =
new gsSolidHalfEdge<T>(n,face0,nFace+1,convex,heLoopN);
907 gsSolidHalfEdgeHandle tn =
new gsSolidHalfEdge<T>(t,face1,nFace+2,convex,hemLoopN);
908 gsSolidHalfEdgeHandle ns =
new gsSolidHalfEdge<T>(n,face1,nFace+3,convex,hemLoopN);
917 hem->prev->next = tn;
919 ns->next = hem->next;
920 hem->next->prev = ns;
922 tn->prev = hem->prev;
930 this->edge.push_back(sn);
931 this->edge.push_back(nt);
932 this->edge.push_back(tn);
933 this->edge.push_back(ns);
936 if ((face0->loop).at(he->loopN())==he) (face0->loop).at(he->loopN()) = sn;
937 if ((face1->loop).at(he->mate->loopN())==he->mate) (face1->loop).at(he->mate->loopN()) = tn;
940 if (s->hed == he) s->hed = he->prev->mate;
941 if (t->hed == hem) t->hed = hem->prev->mate;
944 int idmax = he->getId();
945 if (he->mate->getId()>idmax) idmax=he->mate->getId();
946 int idmin = he->getId();
947 if (he->mate->getId()<idmin) idmin=he->mate->getId();
949 for (
size_t i = idmax+1; i < this->nHalfEdges(); i++)
951 this->edge[i]->setId(i-1);
953 this->edge.erase(this->edge.begin() + idmax);
955 for (
size_t i = idmin+1; i < this->nHalfEdges(); i++)
957 this->edge[i]->setId(i-1);
959 this->edge.erase(this->edge.begin() + idmin);
961 this->numVertices = this->nVertices();
962 this->numHalfEdges = this->nHalfEdges();
963 this->numHalfFaces = this->nHalfFaces();
964 this->numVolumes = this->nVolumes();
965 gsDebug<<
"A new vertex is added to the halfedge with source: "<<*he->source<<
966 " and target: "<<*he->target()<<std::endl;