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
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
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
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
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
00263
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