00001
00006 #include "CirclePattern.h"
00007 #include "util.h"
00008 #include "Mesh.h"
00009
00010 using namespace std;
00011
00012 static double M2_PI = 2*M_PI;
00013
00023 double CirclePattern::ImLi2Sum (const double& theta, const double& x,
00024 const double& tanHalfThetaStar, const double& clThetaStar)
00025 {
00026 double tStar = M_PI - theta;
00027 double p = 2*atan(tanh(0.5*x)*tanHalfThetaStar);
00028
00029 return p*x + Cl2(p + tStar) + Cl2(-p + tStar) - clThetaStar;
00030 }
00031
00040 double CirclePattern::evaluateEnergy (Mesh * mesh, double *xx) {
00041 int i, j;
00042 double energy = 0;
00043 for (i = 0; i < mesh->numFaces(); i++) {
00044 energy += xx[i];
00045 }
00046
00047 energy = M2_PI*energy;
00048
00049 Mesh::HalfEdgeIterator hIter = mesh->halfEdgeIterator();
00050 for (hIter.reset(); !hIter.end(); hIter++) {
00051 Edge * e = hIter.half_edge();
00052
00053 if (!e->isBoundary()) {
00054 i = e->face->ID;
00055 j = e->pair->face->ID;
00056 if (i > j) {
00057 double theta = e->theta();
00058 energy += ImLi2Sum(theta, xx[i] - xx[j], e->tanHalfTStar(), e->Cl2TStar());
00059 energy -= (M_PI - theta)*(xx[i] + xx[j]);
00060 }
00061 }
00062 else {
00063 if (e->face) {
00064 i = e->face->ID;
00065 energy -= 2*(M_PI - e->theta())*(xx[i]);
00066 }
00067 }
00068 }
00069 return energy;
00070 }
00071
00080 void CirclePattern::computeGradient (Mesh * mesh, double * xx, double * grad) {
00081
00082 Mesh::FaceIterator fIter = mesh->faceIterator();
00083
00084
00085 int i, j;
00086 for (i = 0; i < mesh->numFaces(); i++)
00087 grad[i] = M2_PI;
00088
00089
00090 Mesh::HalfEdgeIterator hIter = mesh->halfEdgeIterator();
00091 for (hIter.reset(); !hIter.end(); hIter++) {
00092 Edge * e = hIter.half_edge();
00093 if (!e->isBoundary()) {
00094 i = e->face->ID;
00095 j = e->pair->face->ID;
00096 if (i > j) {
00097 grad[i] -= fTheta2(e->cosTheta(), e->sinTheta(), xx[j] - xx[i]);
00098 grad[j] -= fTheta2(e->cosTheta(), e->sinTheta(), xx[i] - xx[j]);
00099 }
00100 }
00101 else if (e->face) {
00102 i = e->face->ID;
00103 grad[i] -= 2*(M_PI - e->theta());
00104 }
00105 }
00106
00107 }
00108
00110 void CirclePattern::buildSparsityForHessian (Mesh * mesh, int * hessI, int * hessJ) {
00111 int i, k, j;
00112
00114 for (k = 0; k < mesh->numFaces(); k++) {
00115 hessI[k] = k;
00116 hessJ[k] = k;
00117 }
00118
00119 k = mesh->numFaces();
00121 Mesh::HalfEdgeIterator hIter = mesh->halfEdgeIterator();
00122 for (hIter.reset(); !hIter.end(); hIter++) {
00123 if (!hIter.half_edge()->isBoundary()) {
00124 i = hIter.half_edge()->face->ID;
00125 j = hIter.half_edge()->pair->face->ID;
00126 if (i > j) {
00127 hessI[k] = i;
00128 hessJ[k] = j;
00129 k++;
00130 }
00131 }
00132 }
00133 }
00134
00142 void CirclePattern::computeHessian (Mesh * mesh, double * xx, double * hessval) {
00143 for (int k = 0; k < mesh->numFaces(); k++)
00144 hessval[k] = 0;
00145
00146 int count = mesh->numFaces();
00147 int i,j;
00148 Mesh::HalfEdgeIterator hIter = mesh->halfEdgeIterator();
00149 for (hIter.reset(); !hIter.end(); hIter++) {
00150 Edge * e = hIter.half_edge();
00151 if (!e->isBoundary()) {
00152 i = e->face->ID;
00153 j = e->pair->face->ID;
00154 if (i > j) {
00155 double ximj = xx[i] - xx[j];
00156 double fThPrime2 = fThetaPrime2(e->cosTheta(), e->sinTheta(), ximj);
00157 hessval[count] = -fThPrime2;
00158 hessval[i] += fThPrime2;
00159 hessval[j] += fThPrime2;
00160 count++;
00161 }
00162 }
00163 }
00164 }
00165