180void VisualizationHelpers<Scalar, LocalOrdinal, GlobalOrdinal, Node>::doConvexHulls3D(std::vector<int>& vertices, std::vector<int>& geomSizes, LO numLocalAggs, LO numFineNodes,
const std::vector<bool>& ,
const ArrayRCP<LO>& vertex2AggId,
const Teuchos::ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::coordinateType>& xCoords,
const Teuchos::ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::coordinateType>& yCoords,
const Teuchos::ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::coordinateType>& zCoords) {
185 typedef std::list<int>::iterator Iter;
186 for (
int agg = 0; agg < numLocalAggs; agg++) {
187 std::list<int> aggNodes;
188 for (
int i = 0; i < numFineNodes; i++) {
189 if (vertex2AggId[i] == agg)
190 aggNodes.push_back(i);
194 "CoarseningVisualization::doConvexHulls3D: aggregate contains zero nodes!");
195 if (aggNodes.size() == 1) {
196 vertices.push_back(aggNodes.front());
197 geomSizes.push_back(1);
199 }
else if (aggNodes.size() == 2) {
200 vertices.push_back(aggNodes.front());
201 vertices.push_back(aggNodes.back());
202 geomSizes.push_back(2);
206 bool areCollinear =
true;
208 Iter it = aggNodes.begin();
209 myVec3 firstVec(xCoords[*it], yCoords[*it], zCoords[*it]);
213 myVec3 secondVec(xCoords[*it], yCoords[*it], zCoords[*it]);
214 comp = vecSubtract(secondVec, firstVec);
217 for (; it != aggNodes.end(); it++) {
218 myVec3 thisVec(xCoords[*it], yCoords[*it], zCoords[*it]);
219 myVec3 cross = crossProduct(vecSubtract(thisVec, firstVec), comp);
220 if (mymagnitude(cross) > 1e-10) {
221 areCollinear =
false;
229 Iter min = aggNodes.begin();
230 Iter max = aggNodes.begin();
231 Iter it = ++aggNodes.begin();
232 for (; it != aggNodes.end(); it++) {
233 if (xCoords[*it] < xCoords[*min])
235 else if (xCoords[*it] == xCoords[*min]) {
236 if (yCoords[*it] < yCoords[*min])
238 else if (yCoords[*it] == yCoords[*min]) {
239 if (zCoords[*it] < zCoords[*min]) min = it;
242 if (xCoords[*it] > xCoords[*max])
244 else if (xCoords[*it] == xCoords[*max]) {
245 if (yCoords[*it] > yCoords[*max])
247 else if (yCoords[*it] == yCoords[*max]) {
248 if (zCoords[*it] > zCoords[*max])
253 vertices.push_back(*min);
254 vertices.push_back(*max);
255 geomSizes.push_back(2);
258 bool areCoplanar =
true;
261 Iter vert = aggNodes.begin();
262 myVec3 v1(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
264 myVec3 v2(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
266 myVec3 v3(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
269 while (mymagnitude(crossProduct(vecSubtract(v1, v2), vecSubtract(v1, v3))) < 1e-10) {
271 v3 =
myVec3(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
274 for (; vert != aggNodes.end(); vert++) {
275 myVec3 pt(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
276 if (fabs(pointDistFromTri(pt, v1, v2, v3)) > 1e-12) {
283 myVec3 planeNorm = getNorm(v1, v2, v3);
284 planeNorm.
x = fabs(planeNorm.
x);
285 planeNorm.
y = fabs(planeNorm.
y);
286 planeNorm.
z = fabs(planeNorm.
z);
287 std::vector<myVec2> points;
288 std::vector<int> nodes;
289 if (planeNorm.
x >= planeNorm.
y && planeNorm.
x >= planeNorm.
z) {
291 for (Iter it = aggNodes.begin(); it != aggNodes.end(); it++) {
292 nodes.push_back(*it);
293 points.push_back(
myVec2(yCoords[*it], zCoords[*it]));
296 if (planeNorm.
y >= planeNorm.
x && planeNorm.
y >= planeNorm.
z) {
298 for (Iter it = aggNodes.begin(); it != aggNodes.end(); it++) {
299 nodes.push_back(*it);
300 points.push_back(
myVec2(xCoords[*it], zCoords[*it]));
303 if (planeNorm.
z >= planeNorm.
x && planeNorm.
z >= planeNorm.
y) {
304 for (Iter it = aggNodes.begin(); it != aggNodes.end(); it++) {
305 nodes.push_back(*it);
306 points.push_back(
myVec2(xCoords[*it], yCoords[*it]));
309 std::vector<int> convhull2d = giftWrap(points, nodes, xCoords, yCoords);
310 geomSizes.push_back(convhull2d.size());
311 vertices.reserve(vertices.size() + convhull2d.size());
312 for (
size_t i = 0; i < convhull2d.size(); i++)
313 vertices.push_back(convhull2d[i]);
317 Iter exIt = aggNodes.begin();
318 int extremeSix[] = {*exIt, *exIt, *exIt, *exIt, *exIt, *exIt};
320 for (; exIt != aggNodes.end(); exIt++) {
322 if (xCoords[*it] < xCoords[extremeSix[0]] ||
323 (xCoords[*it] == xCoords[extremeSix[0]] && yCoords[*it] < yCoords[extremeSix[0]]) ||
324 (xCoords[*it] == xCoords[extremeSix[0]] && yCoords[*it] == yCoords[extremeSix[0]] && zCoords[*it] < zCoords[extremeSix[0]]))
326 if (xCoords[*it] > xCoords[extremeSix[1]] ||
327 (xCoords[*it] == xCoords[extremeSix[1]] && yCoords[*it] > yCoords[extremeSix[1]]) ||
328 (xCoords[*it] == xCoords[extremeSix[1]] && yCoords[*it] == yCoords[extremeSix[1]] && zCoords[*it] > zCoords[extremeSix[1]]))
330 if (yCoords[*it] < yCoords[extremeSix[2]] ||
331 (yCoords[*it] == yCoords[extremeSix[2]] && zCoords[*it] < zCoords[extremeSix[2]]) ||
332 (yCoords[*it] == yCoords[extremeSix[2]] && zCoords[*it] == zCoords[extremeSix[2]] && xCoords[*it] < xCoords[extremeSix[2]]))
334 if (yCoords[*it] > yCoords[extremeSix[3]] ||
335 (yCoords[*it] == yCoords[extremeSix[3]] && zCoords[*it] > zCoords[extremeSix[3]]) ||
336 (yCoords[*it] == yCoords[extremeSix[3]] && zCoords[*it] == zCoords[extremeSix[3]] && xCoords[*it] > xCoords[extremeSix[3]]))
338 if (zCoords[*it] < zCoords[extremeSix[4]] ||
339 (zCoords[*it] == zCoords[extremeSix[4]] && xCoords[*it] < xCoords[extremeSix[4]]) ||
340 (zCoords[*it] == zCoords[extremeSix[4]] && xCoords[*it] == xCoords[extremeSix[4]] && yCoords[*it] < yCoords[extremeSix[4]]))
342 if (zCoords[*it] > zCoords[extremeSix[5]] ||
343 (zCoords[*it] == zCoords[extremeSix[5]] && xCoords[*it] > xCoords[extremeSix[5]]) ||
344 (zCoords[*it] == zCoords[extremeSix[5]] && xCoords[*it] == xCoords[extremeSix[5]] && yCoords[*it] > zCoords[extremeSix[5]]))
348 for (
int i = 0; i < 6; i++) {
349 myVec3 thisExtremeVec(xCoords[extremeSix[i]], yCoords[extremeSix[i]], zCoords[extremeSix[i]]);
350 extremeVectors[i] = thisExtremeVec;
355 for (
int i = 0; i < 5; i++) {
356 for (
int j = i + 1; j < 6; j++) {
357 double thisDist = distance(extremeVectors[i], extremeVectors[j]);
359 if (thisDist > maxDist && thisDist - maxDist > 1e-12) {
366 std::list<myTriangle> hullBuilding;
368 aggNodes.remove(extremeSix[base1]);
369 aggNodes.remove(extremeSix[base2]);
372 tri.
v1 = extremeSix[base1];
373 tri.
v2 = extremeSix[base2];
377 myVec3 b1 = extremeVectors[base1];
378 myVec3 b2 = extremeVectors[base2];
380 for (Iter node = aggNodes.begin(); node != aggNodes.end(); node++) {
381 myVec3 nodePos(xCoords[*node], yCoords[*node], zCoords[*node]);
382 double dist = mymagnitude(crossProduct(vecSubtract(nodePos, b1), vecSubtract(nodePos, b2))) / mymagnitude(vecSubtract(b2, b1));
384 if (dist > maxDist && dist - maxDist > 1e-12) {
391 hullBuilding.push_back(tri);
392 myVec3 b3(xCoords[*thirdNode], yCoords[*thirdNode], zCoords[*thirdNode]);
393 aggNodes.erase(thirdNode);
396 int fourthVertex = -1;
397 for (Iter node = aggNodes.begin(); node != aggNodes.end(); node++) {
398 myVec3 thisNode(xCoords[*node], yCoords[*node], zCoords[*node]);
399 double nodeDist = pointDistFromTri(thisNode, b1, b2, b3);
401 if (nodeDist > maxDist && nodeDist - maxDist > 1e-12) {
403 fourthVertex = *node;
406 aggNodes.remove(fourthVertex);
407 myVec3 b4(xCoords[fourthVertex], yCoords[fourthVertex], zCoords[fourthVertex]);
410 tri = hullBuilding.front();
411 tri.
v1 = fourthVertex;
412 hullBuilding.push_back(tri);
413 tri = hullBuilding.front();
414 tri.
v2 = fourthVertex;
415 hullBuilding.push_back(tri);
416 tri = hullBuilding.front();
417 tri.
v3 = fourthVertex;
418 hullBuilding.push_back(tri);
420 myVec3 barycenter((b1.
x + b2.
x + b3.
x + b4.
x) / 4.0, (b1.
y + b2.
y + b3.
y + b4.
y) / 4.0, (b1.
z + b2.
z + b3.
z + b4.
z) / 4.0);
421 for (std::list<myTriangle>::iterator tetTri = hullBuilding.begin(); tetTri != hullBuilding.end(); tetTri++) {
422 myVec3 triVert1(xCoords[tetTri->v1], yCoords[tetTri->v1], zCoords[tetTri->v1]);
423 myVec3 triVert2(xCoords[tetTri->v2], yCoords[tetTri->v2], zCoords[tetTri->v2]);
424 myVec3 triVert3(xCoords[tetTri->v3], yCoords[tetTri->v3], zCoords[tetTri->v3]);
425 myVec3 trinorm = getNorm(triVert1, triVert2, triVert3);
426 myVec3 ptInPlane = tetTri == hullBuilding.begin() ? b1 : b4;
427 if (isInFront(barycenter, ptInPlane, trinorm)) {
430 int temp = tetTri->v1;
431 tetTri->v1 = tetTri->v2;
443 for (std::list<myTriangle>::iterator tetTri = hullBuilding.begin(); tetTri != hullBuilding.end(); tetTri++) {
444 myVec3 triVert1(xCoords[tetTri->v1], yCoords[tetTri->v1], zCoords[tetTri->v1]);
445 myVec3 triVert2(xCoords[tetTri->v2], yCoords[tetTri->v2], zCoords[tetTri->v2]);
446 myVec3 triVert3(xCoords[tetTri->v3], yCoords[tetTri->v3], zCoords[tetTri->v3]);
447 trinorms[index] = getNorm(triVert1, triVert2, triVert3);
450 std::list<int> startPoints1;
451 std::list<int> startPoints2;
452 std::list<int> startPoints3;
453 std::list<int> startPoints4;
456 Iter point = aggNodes.begin();
457 while (!aggNodes.empty())
459 myVec3 pointVec(xCoords[*point], yCoords[*point], zCoords[*point]);
462 if (isInFront(pointVec, b1, trinorms[0])) {
463 startPoints1.push_back(*point);
464 point = aggNodes.erase(point);
465 }
else if (isInFront(pointVec, b4, trinorms[1])) {
466 startPoints2.push_back(*point);
467 point = aggNodes.erase(point);
468 }
else if (isInFront(pointVec, b4, trinorms[2])) {
469 startPoints3.push_back(*point);
470 point = aggNodes.erase(point);
471 }
else if (isInFront(pointVec, b4, trinorms[3])) {
472 startPoints4.push_back(*point);
473 point = aggNodes.erase(point);
475 point = aggNodes.erase(point);
480 typedef std::list<myTriangle>::iterator TriIter;
481 TriIter firstTri = hullBuilding.begin();
490 if (!startPoints1.empty())
491 processTriangle(hullBuilding, start1, startPoints1, barycenter, xCoords, yCoords, zCoords);
492 if (!startPoints2.empty())
493 processTriangle(hullBuilding, start2, startPoints2, barycenter, xCoords, yCoords, zCoords);
494 if (!startPoints3.empty())
495 processTriangle(hullBuilding, start3, startPoints3, barycenter, xCoords, yCoords, zCoords);
496 if (!startPoints4.empty())
497 processTriangle(hullBuilding, start4, startPoints4, barycenter, xCoords, yCoords, zCoords);
500 vertices.reserve(vertices.size() + 3 * hullBuilding.size());
501 for (TriIter hullTri = hullBuilding.begin(); hullTri != hullBuilding.end(); hullTri++) {
502 vertices.push_back(hullTri->v1);
503 vertices.push_back(hullTri->v2);
504 vertices.push_back(hullTri->v3);
505 geomSizes.push_back(3);
659 typedef std::list<int>::iterator Iter;
660 typedef std::list<myTriangle>::iterator TriIter;
661 typedef list<pair<int, int> >::iterator EdgeIter;
664 myVec3 v1(xCoords[tri.
v1], yCoords[tri.
v1], zCoords[tri.
v1]);
665 myVec3 v2(xCoords[tri.
v2], yCoords[tri.
v2], zCoords[tri.
v2]);
666 myVec3 v3(xCoords[tri.
v3], yCoords[tri.
v3], zCoords[tri.
v3]);
668 Iter farPoint = pointsInFront.begin();
669 for (Iter point = pointsInFront.begin(); point != pointsInFront.end(); point++) {
670 myVec3 pointVec(xCoords[*point], yCoords[*point], zCoords[*point]);
671 double dist = pointDistFromTri(pointVec, v1, v2, v3);
673 if (dist > maxDist && dist - maxDist > 1e-12) {
675 farPointVec = pointVec;
681 vector<myTriangle> visible;
682 for (TriIter it = tris.begin(); it != tris.end();) {
683 myVec3 vec1(xCoords[it->v1], yCoords[it->v1], zCoords[it->v1]);
684 myVec3 vec2(xCoords[it->v2], yCoords[it->v2], zCoords[it->v2]);
685 myVec3 vec3(xCoords[it->v3], yCoords[it->v3], zCoords[it->v3]);
686 myVec3 norm = getNorm(vec1, vec2, vec3);
687 if (isInFront(farPointVec, vec1, norm)) {
688 visible.push_back(*it);
695 list<pair<int, int> > horizon;
698 for (vector<myTriangle>::iterator it = visible.begin(); it != visible.end(); it++) {
699 pair<int, int> e1(it->v1, it->v2);
700 pair<int, int> e2(it->v2, it->v3);
701 pair<int, int> e3(it->v1, it->v3);
703 if (e1.first > e1.second) {
705 e1.first = e1.second;
708 if (e2.first > e2.second) {
710 e2.first = e2.second;
713 if (e3.first > e3.second) {
715 e3.first = e3.second;
718 horizon.push_back(e1);
719 horizon.push_back(e2);
720 horizon.push_back(e3);
726 EdgeIter it = horizon.begin();
727 while (it != horizon.end()) {
728 int occur = count(horizon.begin(), horizon.end(), *it);
730 pair<int, int> removeVal = *it;
731 while (removeVal == *it && !(it == horizon.end()))
732 it = horizon.erase(it);
738 list<myTriangle> newTris;
739 for (EdgeIter it = horizon.begin(); it != horizon.end(); it++) {
740 myTriangle t(it->first, it->second, *farPoint);
741 newTris.push_back(t);
744 vector<myTriangle> trisToProcess;
745 vector<list<int> > newFrontPoints;
746 for (TriIter it = newTris.begin(); it != newTris.end(); it++) {
747 myVec3 t1(xCoords[it->v1], yCoords[it->v1], zCoords[it->v1]);
748 myVec3 t2(xCoords[it->v2], yCoords[it->v2], zCoords[it->v2]);
749 myVec3 t3(xCoords[it->v3], yCoords[it->v3], zCoords[it->v3]);
750 if (isInFront(barycenter, t1, getNorm(t1, t2, t3))) {
759 myVec3 outwardNorm = getNorm(t1, t2, t3);
762 trisToProcess.push_back(tris.back());
764 list<int> newInFront;
765 for (Iter point = pointsInFront.begin(); point != pointsInFront.end();) {
766 myVec3 pointVec(xCoords[*point], yCoords[*point], zCoords[*point]);
767 if (isInFront(pointVec, t1, outwardNorm)) {
768 newInFront.push_back(*point);
769 point = pointsInFront.erase(point);
773 newFrontPoints.push_back(newInFront);
775 vector<myTriangle> allRemoved;
776 for (
int i = 0; i < int(trisToProcess.size()); i++) {
777 if (!newFrontPoints[i].empty()) {
780 if (find(allRemoved.begin(), allRemoved.end(), trisToProcess[i]) == allRemoved.end() && !(trisToProcess[i] == tri)) {
781 vector<myTriangle> removedList = processTriangle(tris, trisToProcess[i], newFrontPoints[i], barycenter, xCoords, yCoords, zCoords);
782 for (
int j = 0; j < int(removedList.size()); j++)
783 allRemoved.push_back(removedList[j]);
793 "CoarseningVisualization::giftWrap: Gift wrap algorithm input has to have at least 3 points!");
797 double min_x = points[0].x;
798 double min_y = points[0].y;
799 for (std::vector<int>::iterator it = nodes.begin(); it != nodes.end(); it++) {
800 int i = it - nodes.begin();
801 if (points[i].x < min_x) min_x = points[i].x;
802 if (points[i].y < min_y) min_y = points[i].y;
807 myVec2 dummy_min(min_x, min_y);
810 std::vector<int> hull;
812 double mindist = distance(min, dummy_min);
813 std::vector<int>::iterator minNode = nodes.begin();
814 for (std::vector<int>::iterator it = nodes.begin(); it != nodes.end(); it++) {
815 int i = it - nodes.begin();
816 if (distance(points[i], dummy_min) < mindist) {
817 mindist = distance(points[i], dummy_min);
822 hull.push_back(*minNode);
824 std::vector<int> hull;
825 std::vector<int>::iterator minNode = nodes.begin();
827 for (std::vector<int>::iterator it = nodes.begin(); it != nodes.end(); it++) {
828 int i = it - nodes.begin();
829 if (points[i].x < min.
x || (fabs(points[i].x - min.
x) < 1e-10 && points[i].y < min.
y)) {
834 hull.push_back(*minNode);
837 bool includeMin =
false;
840 std::vector<int>::iterator leftMost = nodes.begin();
841 if (!includeMin && leftMost == minNode) {
844 std::vector<int>::iterator it = leftMost;
846 for (; it != nodes.end(); it++) {
847 if (it == minNode && !includeMin)
849 if (*it == hull.back())
853 myVec2 leftMostVec = points[leftMost - nodes.begin()];
854 myVec2 lastVec(xCoords[hull.back()], yCoords[hull.back()]);
855 myVec2 testNorm = getNorm(vecSubtract(leftMostVec, lastVec));
857 myVec2 itVec(xCoords[*it], yCoords[*it]);
858 double dotProd = dotProduct(testNorm, vecSubtract(itVec, lastVec));
859 if (-1e-8 < dotProd && dotProd < 1e-8) {
862 myVec2 itDist = vecSubtract(itVec, lastVec);
863 myVec2 leftMostDist = vecSubtract(leftMostVec, lastVec);
864 if (fabs(itDist.
x) + fabs(itDist.
y) > fabs(leftMostDist.
x) + fabs(leftMostDist.
y)) {
867 }
else if (dotProd > 0) {
872 if (*leftMost == *minNode)
874 hull.push_back(*leftMost);