00001
00006 #include "AnglesOptimization.h"
00007 #include <iostream>
00008 #include "util.h"
00009 #include "Mesh.h"
00010 #include <fstream>
00011 #include <iomanip>
00012
00013 using namespace std;
00014
00015 const double AnglesOptimization::epsRange = 1.0e-3;
00016
00017 AnglesOptimization::AnglesOptimization(Mesh *_mesh, const MSKenv_t & env) {
00018 mesh = _mesh;
00019
00020 NUMVAR = mesh->numFaces() * 3;
00021 NUMCON = mesh->numFaces() + mesh->numVertices() + mesh->numEdges() - mesh->numBoundary();
00022 NUMANZ = 3*NUMVAR - mesh->numBoundary();
00023 NUMQNZ = NUMVAR;
00024
00026 int r = MSK_RES_OK;
00027 r = MSK_maketask(env, NUMCON, NUMVAR, &task);
00028 check_error (r != MSK_RES_OK, "Cannot make MOSEK task for angle optimization.");
00029 r = MSK_linkfiletotaskstream(task, MSK_STREAM_LOG, "_AngleOptMosekOut.txt", 0);
00030 check_error (r != MSK_RES_OK, "Cannot link MOSEK \"_AngleOptMosekOut.txt\" output file.");
00031 }
00032
00039 void AnglesOptimization::doSolve() {
00040 allocateMosekArrays();
00041 setDataStructres();
00042 optimize();
00043 }
00044
00045 void AnglesOptimization::setDataStructres() {
00046
00048 int k = 0;
00049 int kBefore = 0;
00050
00052 Mesh::FaceIterator fIter = mesh->faceIterator();
00053 for ( ; !fIter.end(); fIter++) {
00054 k = fIter.face()->ID;
00055 bkc[k] = MSK_BK_FX;
00056 blc[k] = M_PI;
00057 buc[k] = M_PI;
00058 }
00059
00060 kBefore = mesh->numFaces();
00061
00065 Mesh::VertexIterator vIter = mesh->vertexIterator();
00066 for (; !vIter.end(); vIter++) {
00067 Vertex * v = vIter.vertex();
00068 k = kBefore + v->ID;
00069
00070 if (!v->constrained) {
00071 if (!v->isBoundary()) {
00072 bkc[k] = MSK_BK_FX;
00073 blc[k] = 2*M_PI;
00074 buc[k] = 2*M_PI;
00075 }
00076 else {
00077 bkc[k] = MSK_BK_RA;
00078 blc[k] = 0;
00079 buc[k] = 2*M_PI;
00080 }
00081 }
00082 else {
00083 if (v->max_cone_angle == v->min_cone_angle)
00084 bkc[k] = MSK_BK_FX;
00085 else
00086 bkc[k] = MSK_BK_RA;
00087 blc[k] = v->min_cone_angle*M_PI;
00088 buc[k] = v->max_cone_angle*M_PI;
00089 }
00090 }
00091
00092 kBefore += mesh->numVertices();
00093 k = kBefore;
00094
00096 Mesh::EdgeIterator eIter = mesh->edgeIterator();
00097 for ( ; !eIter.end(); eIter++) {
00098 Edge * e = eIter.edge();
00099 if (!e->isBoundary()) {
00100 e->ID = k;
00101 e->pair->ID = e->ID;
00102
00103 bkc[k] = MSK_BK_RA;
00104 blc[k] = epsRange;
00105 buc[k] = M_PI - epsRange;
00106 k++;
00107 }
00108 }
00109
00110
00111
00112 Mesh::HalfEdgeIterator hIter = mesh->halfEdgeIterator();
00113 for (; !hIter.end(); hIter++) {
00114 Edge * e = hIter.half_edge();
00115 if (e->face) {
00116 int vId = e->oppositeVertex()->ID;
00117 int fId = e->face->ID;
00118 int eId = e->ID;
00119
00120 vId += mesh->numFaces();
00121
00122 blc[fId] -= e->alphaOposite;
00123 buc[fId] -= e->alphaOposite;
00124 blc[vId] -= e->alphaOposite;
00125 buc[vId] -= e->alphaOposite;
00126
00127 if (!e->isBoundary()) {
00128 blc[eId] -= e->alphaOposite;
00129 buc[eId] -= e->alphaOposite;
00130 }
00131 }
00132 }
00133
00134
00136 int currPtr = 0;
00137 int count = 0;
00138
00139 for (hIter.reset(); !hIter.end(); hIter++) {
00140 Edge * e = hIter.half_edge();
00141 if (e->face) {
00142 Edge * e = hIter.half_edge();
00143
00144
00145 c[count] = 0.0;
00146
00147
00148 ptrb[count] = currPtr;
00149
00150 if (e->isBoundary())
00151 ptre[count] = currPtr + 2;
00152 else
00153 ptre[count] = currPtr + 3;
00154
00155 int fId = e->face->ID;
00156 sub[currPtr] = fId;
00157 val[currPtr] = 1.0;
00158 currPtr++;
00159
00160 int vId = e->oppositeVertex()->ID;
00161 vId += mesh->numFaces();
00162 sub[currPtr] = vId;
00163 val[currPtr] = 1.0;
00164 currPtr++;
00165
00166 if (!e->isBoundary()) {
00167 int eId = e->ID;
00168 sub[currPtr] = eId;
00169 val[currPtr] = 1.0;
00170 currPtr++;
00171 }
00172
00173
00174 bkx[count] = MSK_BK_RA;
00175 blx[count] = epsRange - e->alphaOposite;
00176 bux[count] = (M_PI - epsRange) - e->alphaOposite;
00177 count++;
00178 }
00179 }
00180 }
00181
00182 void AnglesOptimization::optimize() {
00183 int r = MSK_RES_OK;
00184 r = MSK_inputdata(task, NUMCON,NUMVAR, NUMCON,NUMVAR, c,
00185 0.0, ptrb, ptre, sub, val, bkc, blc, buc, bkx, blx, bux);
00186
00187 check_error ( r != MSK_RES_OK,
00188 "Could not input constraints for angle optimization.\n Check \"AngleOptMosekOut.txt\" for output." );
00189
00191 int count = 0;
00192 for (count = 0; count < NUMVAR; count++) {
00193 qsubi[count] = count;
00194 qsubj[count] = count;
00195 qval[count] = 1;
00196 }
00197
00198 r = MSK_putqobj(task, NUMQNZ, qsubi, qsubj, qval);
00199 check_error ( r != MSK_RES_OK,
00200 "Could not input objective for angle optimization.\n Check \"AngleOptMosekOut.txt\" for output." );
00201
00202
00204 r = MSK_optimize(task);
00205 check_error ( r != MSK_RES_OK,
00206 "Could not solve angle optimization. Possibly the problem is infisible.\n Check \"AngleOptMosekOut.txt\" for output." );
00207
00209 r = MSK_solutionsummary(task, MSK_STREAM_ERR);
00210 check_error ( r != MSK_RES_OK,
00211 "Could not output solution summary.\n Check \"AngleOptMosekOut.txt\" for output." );
00212
00213
00215 int ps, ss;
00216 r = MSK_getsolution (task, MSK_SOL_ITR, &ps, &ss, NULL, NULL, NULL, NULL, xx, NULL, NULL, NULL, NULL, NULL, NULL);
00217
00218 check_error ( r != MSK_RES_OK, "Could not get solution of angle optimization.\n Check \"AngleOptMosekOut.txt\" for output." );
00219 check_error ( ps != MSK_PRO_STA_PRIM_AND_DUAL_FEAS,
00220 "Either problem is infisible or could not find optimal solution for some other reason.\n Check \"AngleOptMosekOut.txt\" for output." );
00221
00223 Mesh::HalfEdgeIterator hIter = mesh->halfEdgeIterator();
00224 count = 0;
00225 for (hIter.reset(); !hIter.end(); hIter++) {
00226 Edge * e = hIter.half_edge();
00227 if (e->face)
00228 e->alphaOposite = e->alphaOposite + xx[count++];
00229 else
00230 e->alphaOposite = 0;
00231 }
00232
00233
00235 Mesh::EdgeIterator eIter = mesh->edgeIterator();
00236 for (eIter.reset(); !eIter.end(); eIter++){
00237 Edge * e = eIter.edge();
00238 e->setTheta (M_PI - e->alphaOposite - e->pair->alphaOposite);
00239 e->pair->setTheta (e->theta());
00240 }
00241
00242 Mesh::VertexIterator vIter = mesh->vertexIterator();
00243 for (vIter.reset(); !vIter.end(); vIter++) {
00244 vIter.vertex()->cone_angle = 0;
00245 }
00246
00247 for (eIter.reset(); !eIter.end(); eIter++) {
00248 Edge * e = eIter.edge();
00249 e->vertex->cone_angle += e->theta();
00250 e->pair->vertex->cone_angle += e->theta();
00251 }
00252
00253 for (vIter.reset(); !vIter.end(); vIter++) {
00254 vIter.vertex()->cone_angle /= M_PI;
00255 }
00256 }
00257
00258
00259 void AnglesOptimization::allocateMosekArrays() {
00260 bkc = new int[NUMCON]; bkx = new int[NUMVAR];
00261 ptrb = new int[NUMVAR]; ptre = new int[NUMVAR];
00262 sub = new int[NUMANZ];
00263 qsubi = new int[NUMQNZ]; qsubj = new int[NUMQNZ];
00264
00265 blc = new double[NUMCON]; buc = new double[NUMCON];
00266 c = new double[NUMVAR]; blx = new double[NUMVAR];
00267 bux = new double[NUMVAR]; val = new double[NUMANZ];
00268 xx = new double[NUMVAR]; qval = new double[NUMQNZ];
00269 }
00270
00271 void AnglesOptimization::clearMosekArrays() {
00272
00273 if (task) {
00274 delete [] bkc; delete [] bkx; delete [] ptrb;
00275 delete [] ptre; delete [] sub; delete [] qsubi; delete [] qsubj;
00276 delete [] buc; delete [] c; delete [] blx; delete [] blc;
00277 delete [] bux; delete [] val; delete [] xx; delete [] qval;
00278 MSK_deletetask(&task);
00279 task = NULL;
00280 }
00281 }
00282
00283