LineSetSkinningMapping.inl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef SOFA_COMPONENT_MAPPING_LINESETSKINNINGMAPPING_INL
00027 #define SOFA_COMPONENT_MAPPING_LINESETSKINNINGMAPPING_INL
00028
00029 #include <sofa/component/mapping/LineSetSkinningMapping.h>
00030
00031 namespace sofa
00032 {
00033
00034 namespace component
00035 {
00036
00037 namespace mapping
00038 {
00039
00040 template <class BasicMapping>
00041 Vec<3,double> LineSetSkinningMapping<BasicMapping>::projectToSegment( Vec<3,Real>& first, Vec<3,Real>& last, OutCoord& vertice)
00042 {
00043 Vec3d segment,v_f,v_l;
00044
00045 segment = last - first;
00046 v_f = vertice-first;
00047 v_l = vertice-last;
00048
00049 if(v_f*segment>0.0 && -segment*v_l>0.0)
00050 {
00051 double prod = v_f*segment;
00052 return first + (segment * (prod/segment.norm2()));
00053 }
00054 else
00055 {
00056 if (v_l.norm() > v_f.norm())
00057 return first;
00058 else
00059 return last;
00060 }
00061 }
00062
00063 template <class BasicMapping>
00064 double LineSetSkinningMapping<BasicMapping>::convolutionSegment(Vec<3,Real>& first, Vec<3,Real>& last, OutCoord& vertice)
00065 {
00066 int steps = 1000;
00067 double sum = 0.0;
00068 Vec<3,Real> dist, line;
00069
00070 line=last-first;
00071
00072
00073 for(int i=0; i<=steps; i++)
00074 {
00075 dist = ((line * i) / steps) + first - vertice;
00076 sum += pow(1/dist.norm(),weightCoef.getValue());
00077 }
00078
00079 sum *= line.norm()/steps;
00080 return sum;
00081 }
00082
00083 template <class BasicMapping>
00084 void LineSetSkinningMapping<BasicMapping>::init()
00085 {
00086 OutVecCoord& xto = *this->toModel->getX();
00087 InVecCoord& xfrom = *this->fromModel->getX();
00088 t = this->fromModel->getContext()->getMeshTopology();
00089 linesInfluencedByVertice.resize(xto.size());
00090
00091 verticesInfluencedByLine.resize(t->getNbLines());
00092
00093 neighborhoodLinesSet.resize(t->getNbLines());
00094 neighborhood.resize(t->getNbLines());
00095
00096 for(unsigned int line1Index=0; line1Index< (unsigned) t->getNbLines(); line1Index++)
00097 {
00098 const sofa::core::componentmodel::topology::BaseMeshTopology::Line& line1 = t->getLine(line1Index);
00099 for(unsigned int line2Index=0; line2Index< (unsigned) t->getNbLines(); line2Index++)
00100 {
00101 const sofa::core::componentmodel::topology::BaseMeshTopology::Line& line2 = t->getLine(line2Index);
00102 if ((line1[0] == line2[0]) || (line1[0] == line2[1]) || (line1[1] == line2[0]))
00103 {
00104 neighborhoodLinesSet[line1Index].insert(line2Index);
00105 }
00106 }
00107 }
00108
00109 for(unsigned int line1Index=0; line1Index< (unsigned) t->getNbLines(); line1Index++)
00110 {
00111 std::set<int> result;
00112 std::insert_iterator<std::set<int> > res_ins(result, result.begin());
00113
00114 neighborhood[line1Index] = neighborhoodLinesSet[line1Index];
00115
00116 for(unsigned int i=0; i<nvNeighborhood.getValue()-1; i++)
00117 {
00118 for (std::set<int>::const_iterator it = neighborhood[line1Index].begin(), itbegin = it, itend = neighborhood[line1Index].end(); it != itend; it++)
00119 {
00120 set_union(itbegin, itend, neighborhoodLinesSet[(*it)].begin(), neighborhoodLinesSet[(*it)].end(), res_ins);
00121 }
00122
00123 neighborhood[line1Index] = result;
00124 }
00125 }
00126
00127 for(unsigned int verticeIndex=0; verticeIndex<xto.size(); verticeIndex++)
00128 {
00129 double sumWeights = 0.0;
00130 vector<influencedLineType> lines;
00131 lines.resize(t->getNbLines());
00132
00133 for(unsigned int lineIndex=0; lineIndex< (unsigned) t->getNbLines(); lineIndex++)
00134 {
00135 const sofa::core::componentmodel::topology::BaseMeshTopology::Line& line = t->getLine(lineIndex);
00136 double _weight = convolutionSegment(xfrom[line[0]].getCenter(), xfrom[line[1]].getCenter(), xto[verticeIndex]);
00137
00138 for(unsigned int lineInfluencedIndex=0; lineInfluencedIndex<lines.size(); lineInfluencedIndex++)
00139 {
00140 if(lines[lineInfluencedIndex].weight <= _weight)
00141 {
00142 for(unsigned int i=lines.size()-1; i > lineInfluencedIndex; i--)
00143 {
00144 lines[i].lineIndex = lines[i-1].lineIndex;
00145 lines[i].weight = lines[i-1].weight;
00146 lines[i].position = lines[i-1].position;
00147 }
00148 lines[lineInfluencedIndex].lineIndex = lineIndex;
00149 lines[lineInfluencedIndex].weight = _weight;
00150 lines[lineInfluencedIndex].position = xfrom[line[0]].getOrientation().inverseRotate(xto[verticeIndex] - xfrom[line[0]].getCenter());
00151 break;
00152 }
00153 }
00154 }
00155
00156 unsigned int lineInfluencedIndex = 0;
00157 int max = lines[lineInfluencedIndex].lineIndex;
00158 sumWeights += lines[lineInfluencedIndex].weight;
00159 linesInfluencedByVertice[verticeIndex].push_back(lines[lineInfluencedIndex]);
00160 influencedVerticeType vertice;
00161 vertice.verticeIndex = verticeIndex;
00162 vertice.weight = lines[lineInfluencedIndex].weight;
00163 vertice.position = lines[lineInfluencedIndex].position;
00164 verticesInfluencedByLine[lineInfluencedIndex].push_back(vertice);
00165
00166 lineInfluencedIndex++;
00167
00168 while (linesInfluencedByVertice[verticeIndex].size() < numberInfluencedLines.getValue() && lineInfluencedIndex < lines.size())
00169 {
00170 if (neighborhood[max].count(lines[lineInfluencedIndex].lineIndex) != 0)
00171 {
00172 sumWeights += lines[lineInfluencedIndex].weight;
00173 linesInfluencedByVertice[verticeIndex].push_back(lines[lineInfluencedIndex]);
00174 vertice.verticeIndex = verticeIndex;
00175 vertice.weight = lines[lineInfluencedIndex].weight;
00176 vertice.position = lines[lineInfluencedIndex].position;
00177 verticesInfluencedByLine[lineInfluencedIndex].push_back(vertice);
00178 }
00179 lineInfluencedIndex++;
00180 }
00181
00182 for (unsigned int influencedLineIndex=0; influencedLineIndex<linesInfluencedByVertice[verticeIndex].size(); influencedLineIndex++)
00183 linesInfluencedByVertice[verticeIndex][influencedLineIndex].weight /= sumWeights;
00184 }
00185 }
00186
00187 template <class BasicMapping>
00188 void LineSetSkinningMapping<BasicMapping>::reinit()
00189 {
00190 linesInfluencedByVertice.clear();
00191 verticesInfluencedByLine.clear();
00192 neighborhoodLinesSet.clear();
00193 neighborhood.clear();
00194
00195 init();
00196 }
00197
00198 template <class BasicMapping>
00199 void LineSetSkinningMapping<BasicMapping>::draw()
00200 {
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 }
00231
00232 template <class BasicMapping>
00233 void LineSetSkinningMapping<BasicMapping>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
00234 {
00235 for (unsigned int verticeIndex=0; verticeIndex<out.size(); verticeIndex++)
00236 {
00237 out[verticeIndex] = typename Out::Coord();
00238 for (unsigned int lineInfluencedIndex=0; lineInfluencedIndex<linesInfluencedByVertice[verticeIndex].size(); lineInfluencedIndex++)
00239 {
00240 influencedLineType iline = linesInfluencedByVertice[verticeIndex][lineInfluencedIndex];
00241 out[verticeIndex] += in[t->getLine(iline.lineIndex)[0]].getCenter()*iline.weight;
00242 out[verticeIndex] += in[t->getLine(iline.lineIndex)[0]].getOrientation().rotate(iline.position*iline.weight);
00243 }
00244 }
00245 }
00246
00247 template <class BasicMapping>
00248 void LineSetSkinningMapping<BasicMapping>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
00249 {
00250 InVecCoord& xfrom = *this->fromModel->getX();
00251
00252 for (unsigned int verticeIndex=0; verticeIndex<out.size(); verticeIndex++)
00253 {
00254 out[verticeIndex] = typename Out::Deriv();
00255 for (unsigned int lineInfluencedIndex=0; lineInfluencedIndex<linesInfluencedByVertice[verticeIndex].size(); lineInfluencedIndex++)
00256 {
00257 influencedLineType iline = linesInfluencedByVertice[verticeIndex][lineInfluencedIndex];
00258 Vec<3,Real> IP = xfrom[t->getLine(iline.lineIndex)[0]].getOrientation().rotate(iline.position);
00259 out[verticeIndex] += (in[t->getLine(iline.lineIndex)[0]].getVCenter() - IP.cross(in[t->getLine(iline.lineIndex)[0]].getVOrientation())) * iline.weight;
00260 }
00261 }
00262 }
00263
00264
00265 template <class BasicMapping>
00266 void LineSetSkinningMapping<BasicMapping>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
00267 {
00268 InVecCoord& xfrom = *this->fromModel->getX();
00269
00270 for(unsigned int lineIndex=0; lineIndex< (unsigned) t->getNbLines(); lineIndex++)
00271 {
00272 for (unsigned int verticeInfluencedIndex=0; verticeInfluencedIndex<verticesInfluencedByLine[lineIndex].size(); verticeInfluencedIndex++)
00273 {
00274 influencedVerticeType vertice = verticesInfluencedByLine[lineIndex][verticeInfluencedIndex];
00275 Vec<3,Real> IP = xfrom[t->getLine(lineIndex)[0]].getOrientation().rotate(vertice.position);
00276 out[vertice.verticeIndex].getVCenter() += in[vertice.verticeIndex] * vertice.weight;
00277 out[vertice.verticeIndex].getVOrientation() += IP.cross(in[vertice.verticeIndex]) * vertice.weight;
00278 }
00279 }
00280 }
00281
00282 template <class BasicMapping>
00283 void LineSetSkinningMapping<BasicMapping>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
00284 {
00285 out.clear();
00286 out.resize(in.size());
00287
00288 InVecCoord& xfrom = *this->fromModel->getX();
00289
00290 for(unsigned int i=0; i<in.size(); i++)
00291 {
00292 for (unsigned int j=0;j<in[i].size();j++)
00293 {
00294 const OutSparseDeriv cIn = in[i][j];
00295 int verticeIndex = cIn.index;
00296 const OutDeriv d = (OutDeriv) cIn.data;
00297
00298 for(unsigned int lineInfluencedIndex=0; lineInfluencedIndex<linesInfluencedByVertice[verticeIndex].size(); lineInfluencedIndex++)
00299 {
00300 influencedLineType iline = linesInfluencedByVertice[verticeIndex][lineInfluencedIndex];
00301 Vec<3,Real> IP = xfrom[t->getLine(iline.lineIndex)[0]].getOrientation().rotate(iline.position);
00302 InDeriv direction;
00303 direction.getVCenter() = d * iline.weight;
00304
00305 direction.getVOrientation() = IP.cross(d) * iline.weight;
00306 out[i].push_back(InSparseDeriv(t->getLine(iline.lineIndex)[0], direction));
00307 }
00308 }
00309 }
00310 }
00311
00312 }
00313
00314 }
00315
00316 }
00317
00318 #endif