Layout.cpp

Go to the documentation of this file.
00001 
00006 #include "Layout.h"
00007 #include "Mesh.h"
00008 #include "CirclePattern.h"
00009 #include "util.h"
00010 #include <iomanip>
00011 #include <fstream>
00012 
00013 using namespace std;
00014 
00017 Layout::Layout(Mesh * _mesh) {
00018    mesh = _mesh;
00019 }
00020 
00021 
00022 
00023 bool Layout::validCuts() {
00024 
00025    bool result = true;
00026 
00027    // Number of connected components
00028    int numConnectedComponents = 0;
00029    Mesh::FaceIterator fIter = mesh->faceIterator();
00030    for (; !fIter.end(); fIter++) {
00031       fIter.face()->check = false;
00032    }
00033    stack<Edge *> toVisit;
00034    for (fIter.reset(); !fIter.end(); fIter++) {
00035       if (!fIter.face()->check) {
00036           numConnectedComponents++;
00037           toVisit.push(fIter.face()->edge);
00038           while (!toVisit.empty()) {
00039              Face * fIn = toVisit.top()->face; 
00040              toVisit.pop();
00041              fIn->check = true;     
00042              fIn->patchID = numConnectedComponents-1;
00043              Face::EdgeAroundIterator iter = fIn->iterator();
00044              for (; !iter.end(); iter++) {
00045                 iter.edge()->patchID       = numConnectedComponents-1;
00046                 iter.edge()->pair->patchID = numConnectedComponents-1;
00047                 iter.vertex()->patchID     = numConnectedComponents-1;
00048                 if (iter.edge()->pair->face && !iter.edge()->pair->face->check)
00049                     toVisit.push(iter.edge()->pair);
00050              }
00051           }
00052       }
00053    }
00054 
00055    double * eulerNums = new double[numConnectedComponents+1];
00056    int i;
00057    for (i = 0; i < numConnectedComponents; i++)
00058       eulerNums[i] = 0;
00059 
00060    Mesh::VertexIterator vIter = mesh->vertexIterator();
00061    for (; !vIter.end(); vIter++)
00062       eulerNums[vIter.vertex()->patchID] += 1;
00063    for (fIter.reset(); !fIter.end(); fIter++)
00064       eulerNums[fIter.face()->patchID] += 1;
00065    Mesh::EdgeIterator eIter = mesh->edgeIterator();
00066    for (; !eIter.end(); eIter++) {
00067       eulerNums[eIter.edge()->patchID] -= 1;
00068    }
00069 
00070    for (i = 0; i < numConnectedComponents; i++) {
00071       cout << "Euler number of patch " << (i+1) << ": " << eulerNums[i] << endl;
00072       check_warn(eulerNums[i] != 1, 
00073           "Patch is not developable!\nMost probably the result layout will not be correct.");
00074       result = false;
00075    }
00076 
00077    delete [] eulerNums;
00078 
00079    for (vIter.reset(); !vIter.end(); vIter++) {
00080       if (vIter.vertex()->constrained) {
00081           check_warn(!vIter.vertex()->isBoundary(), 
00082              "Cone singularity vertex is not on the boundary!\nMost probably the result layout will not be correct.");
00083           result = false;
00084       }
00085    }
00086 
00087    cout << "------------------------------------" << endl;
00088    cout << "After cutting: ";
00089    mesh->computeMeshInfo();
00090    cout << "------------------------------------" << endl;
00091 
00092    return result;
00093 }
00094 
00095 void Layout::computeEdgeLengthAndAngles() {
00096    Mesh::HalfEdgeIterator eIter = mesh->halfEdgeIterator();
00097    for (; !eIter.end(); eIter++) {
00098       Edge * e = eIter.half_edge();
00099       double r;
00100       double phi;
00101       double r2 = -1;
00102       if (!e->isBoundary()) {
00103           r = e->face->r;
00104           r2 = e->pair->face->r;
00105           phi = 0.5*CirclePattern::fTheta2(e->cosTheta(), e->sinTheta(), log(r2) - log(r));
00106 
00107       }
00108       else {
00109           if (!e->face)
00110              e = e->pair;
00111 
00112           r = e->face->r;
00113           phi = M_PI - e->theta();
00114       }
00115 
00116       e->length = 2.0*r*sin(phi);
00117       e->alphaOposite = phi;
00118       if (!e->pair->face) {
00119           e->pair->length = e->length;
00120           e->pair->alphaOposite = 0;
00121       }
00122    }
00123 }
00124 
00125 
00126 void Layout::layoutMesh() {
00127 
00128    Mesh::FaceIterator fIter = mesh->faceIterator();
00129    for (; !fIter.end(); fIter++) {
00130       fIter.face()->check = false;
00131    }
00132 
00133    Mesh::VertexIterator vIter = mesh->vertexIterator();
00134    for (; !vIter.end(); vIter++) {
00135       vIter.vertex()->uv = Vector3(0,0,0);
00136       vIter.vertex()->check = false;
00137    }
00138 
00139    for (fIter.reset(); !fIter.end(); fIter++) {
00140       if (!fIter.face()->check) {
00141           Edge * e = fIter.face()->edge;
00142           e->vertex->uv = Vector3(0,0,-2);
00143           e->next->vertex->uv = Vector3(e->length,0,0);
00144           e->vertex->check = true;
00145           e->next->vertex->check = true;
00146           edgesToFacesTodo.push(e);
00147           while (!edgesToFacesTodo.empty()) {
00148              Edge * toDo = edgesToFacesTodo.top();
00149              edgesToFacesTodo.pop();
00150              putFaceFrom(toDo);
00151           }
00152       }
00153    }
00154 
00155    if (mesh->numConnectedComponents > 1)
00156       movePatches();
00157 }
00158 
00159 void Layout::putFaceFrom(Edge * e) {
00160    if (e->face->check) return;
00161    Edge * prev = e->next->next;
00162  //  if (!prev->vertex->check) {
00164       Vector3 oposite = e->vertex->uv - e->next->vertex->uv;
00166       oposite.normalize();
00168       Vector3 res;
00169       Vector3 start;
00170       double angle, length;
00171       if (fabs(0.5*M_PI - prev->alphaOposite) < fabs(0.5*M_PI - e->next->alphaOposite)) {
00172           angle = prev->alphaOposite;
00173           length = e->next->length;
00174           start = e->next->vertex->uv;
00175       }
00176       else {
00177           angle = -e->next->alphaOposite;
00178           length = prev->length;
00179           oposite.negate();
00180           start = e->vertex->uv;
00181       }
00182 
00183       res[0] =   cos(angle)*oposite[0] + sin(angle)*oposite[1];
00184       res[1] =  -sin(angle)*oposite[0] + cos(angle)*oposite[1];
00185 
00187       prev->vertex->uv = start + res*length;
00188       prev->vertex->check = true;
00189   // }
00190    Face::EdgeAroundIterator iter = e->face->iterator();
00191    for( ; !iter.end(); iter++) {
00192       if (iter.face() && !iter.face()->check)
00193           edgesToFacesTodo.push(iter.edge()->pair);
00194    }
00195    e->face->check = true;
00196 }
00197 
00198 void Layout::movePatches() {
00199    if (mesh->numConnectedComponents == 1)
00200       return;
00201 
00202    /* Compute bounding box for each patch and shift them away from each other */
00203    Vector3 * lowLeftCorner = new Vector3[mesh->numConnectedComponents];
00204    Vector3 * upRightCorner = new Vector3[mesh->numConnectedComponents];
00205    bool * started = new bool[mesh->numConnectedComponents];
00206    for (int i = 0; i < mesh->numConnectedComponents; i++)
00207       started[i] = false;
00208 
00209    int patchID;
00210    Vector3 uv;
00211    Mesh::VertexIterator vIter = mesh->vertexIterator();
00212    for (vIter.reset(); !vIter.end(); vIter++) {
00213       patchID = vIter.vertex()->patchID;
00214       uv = vIter.vertex()->uv;
00215       if (!started[patchID]) {
00216           started[patchID] = true;
00217           lowLeftCorner[patchID] = uv;
00218           upRightCorner[patchID] = uv;
00219       }
00220       else {
00221           if (lowLeftCorner[patchID].x() > uv.x())
00222              lowLeftCorner[patchID].x() = uv.x();
00223           if (lowLeftCorner[patchID].y() > uv.y())
00224              lowLeftCorner[patchID].y() = uv.y();
00225           if (upRightCorner[patchID].x() < uv.x())
00226              upRightCorner[patchID].x() = uv.x();
00227           if (upRightCorner[patchID].y() < uv.y())
00228              upRightCorner[patchID].y() = uv.y();
00229       }
00230    }
00231 
00232    /* Translate all the patches so that the low left coner of each of them is at (0,0) */
00233    for (vIter.reset(); !vIter.end(); vIter++)
00234       vIter.vertex()->uv -= lowLeftCorner[vIter.vertex()->patchID];
00235 
00236 
00237    double maxX = upRightCorner[0].x() - lowLeftCorner[0].x(), 
00238       maxY = upRightCorner[0].y() - lowLeftCorner[0].y();
00239 
00240    for (int i = 1; i < mesh->numConnectedComponents; i++) {
00241       if ((upRightCorner[i].x() - lowLeftCorner[i].x()) > maxX)
00242           maxX = upRightCorner[i].x() - lowLeftCorner[i].x();
00243       if ((upRightCorner[i].y() - lowLeftCorner[i].y()) > maxY)
00244           maxY = upRightCorner[i].y() - lowLeftCorner[i].y();
00245    }
00246    delete [] lowLeftCorner;
00247    delete [] upRightCorner;
00248    delete [] started;
00249 
00250    int boxDim = (int)ceil(sqrt((double)mesh->numConnectedComponents));
00251    Vector3 * shiftPos = new Vector3[mesh->numConnectedComponents];
00252    for (int i = 0; i < boxDim; i++) {
00253       for (int j = 0; j < boxDim; j++) {
00254           patchID = i*boxDim + j;
00255           if (patchID < mesh->numConnectedComponents) {
00256              shiftPos[patchID].x() = maxX*(double)i;
00257              shiftPos[patchID].y() = maxY*(double)j;
00258           }
00259       }
00260    }
00261 
00262    /* Translate all the patches so that the low left coner of each of 
00263    them is at the correct grid position */
00264    for (vIter.reset(); !vIter.end(); vIter++)
00265       vIter.vertex()->uv += shiftPos[vIter.vertex()->patchID];
00266 
00267    delete [] shiftPos;
00268 }
00269 
00270 
00271 
00272 
00273 Layout::~Layout(void) {
00274 }
00275 

Generated on Sat Jun 3 13:33:41 2006 for CirclePatterns by  doxygen 1.4.5