typename SurfaceBase<VertexType,EdgeType,TriangleType>::ctype SurfaceBase<VertexType,EdgeType,TriangleType>::minInteriorAngle(int n) const { ctype minAngle = 2*M_PI; const std::array<int, 3>& p = triangles(n).vertices; for (int i=0; i<3; i++){ StaticVector<ctype,3> a = vertices(p[(i+1)%3]) - vertices(p[i]); StaticVector<ctype,3> b = vertices(p[(i+2)%3]) - vertices(p[i]); ctype angle = acosf(a.dot(b) / (a.length() * b.length())); if (angle<minAngle) minAngle = angle; } return minAngle; }
void ContactMapping<2,ctype>::computeDiscreteDomainDirections(const DirectionFunction<2,ctype>* direction, std::vector<StaticVector<ctype,2> >& normals) { size_t nElements = psurface_.domainSegments.size(); if (!direction) { // ////////////////////////////////////////////////////////// // The contact directions are given as the vertex normals // ////////////////////////////////////////////////////////// normals.resize(psurface_.domainVertices.size()); for (size_t i=0; i<psurface_.domainVertices.size(); i++) normals[i] = StaticVector<ctype,2>(0); for (size_t i=0; i<nElements; i++) { // Compute segment normal int v0 = psurface_.domainSegments[i].points[0]; int v1 = psurface_.domainSegments[i].points[1]; StaticVector<ctype,2> segment; segment[0] = psurface_.domainVertices[v1][0] - psurface_.domainVertices[v0][0]; segment[1] = psurface_.domainVertices[v1][1] - psurface_.domainVertices[v0][1]; StaticVector<ctype,2> segmentNormal; segmentNormal[0] = segment[1]; segmentNormal[1] = -segment[0]; segmentNormal /= segmentNormal.length(); normals[psurface_.domainSegments[i].points[0]] += segmentNormal; normals[psurface_.domainSegments[i].points[1]] += segmentNormal; } for (size_t i=0; i<normals.size(); i++) normals[i] /= normals[i].length(); } else { // Sample the provided analytical contact direction field normals.resize(psurface_.domainVertices.size()); for (size_t i=0; i<psurface_.domainVertices.size(); i++) { if (dynamic_cast<const AnalyticDirectionFunction<2,ctype>*>(direction)) normals[i] = (*dynamic_cast<const AnalyticDirectionFunction<2,ctype>*>(direction))(psurface_.domainVertices[i]); else if (dynamic_cast<const DiscreteDirectionFunction<2,ctype>*>(direction)) normals[i] = (*dynamic_cast<const DiscreteDirectionFunction<2,ctype>*>(direction))(i); else throw(std::runtime_error("Domain direction function not properly set!")); } } }
void ContactMapping<2,ctype>::computeDiscreteTargetDirections(const std::vector<std::array<int,2> >& elements, const DirectionFunction<2,ctype>* direction, std::vector<StaticVector<ctype,2> >& normals) { // Build the normal field normals.resize(psurface_.targetVertices.size()); for (size_t i=0; i<psurface_.targetVertices.size(); i++) normals[i] = StaticVector<ctype,2>(0); if (!direction) { for (int i=0; i<elements.size(); i++) { // Compute segment normal int v0 = elements[i][0]; int v1 = elements[i][1]; StaticVector<ctype,2> segment; segment[0] = psurface_.targetVertices[v1][0] - psurface_.targetVertices[v0][0]; segment[1] = psurface_.targetVertices[v1][1] - psurface_.targetVertices[v0][1]; StaticVector<ctype,2> segmentNormal; segmentNormal[0] = segment[1]; segmentNormal[1] = -segment[0]; segmentNormal /= segmentNormal.length(); normals[elements[i][0]] += segmentNormal; normals[elements[i][1]] += segmentNormal; } for (size_t i=0; i<normals.size(); i++) normals[i] /= normals[i].length(); } else { // Sample the provided analytical contact direction field normals.resize(psurface_.targetVertices.size()); for (size_t i=0; i<psurface_.targetVertices.size(); i++) { if (dynamic_cast<const AnalyticDirectionFunction<2,ctype>*>(direction)) normals[i] = (*dynamic_cast<const AnalyticDirectionFunction<2,ctype>*>(direction))(psurface_.targetVertices[i]); else if (dynamic_cast<const DiscreteDirectionFunction<2,ctype>*>(direction)) normals[i] = (*dynamic_cast<const DiscreteDirectionFunction<2,ctype>*>(direction))(i); else throw(std::runtime_error("Target direction function not properly set!")); } } }
ctype CircularPatch<ctype>::distanceTo(const StaticVector<ctype,3> &p) const { int i, j; ctype bestDist = std::numeric_limits<ctype>::max(); // check point against triangles for (j=0; j<size(); j++){ const DomainTriangle<ctype>& cT = par->triangles(triangles[j]); StaticVector<ctype,3> triPoints[3]; triPoints[0] = par->vertices(cT.vertices[0]); triPoints[1] = par->vertices(cT.vertices[1]); triPoints[2] = par->vertices(cT.vertices[2]); // local base StaticVector<ctype,3> a = triPoints[1] - triPoints[0]; StaticVector<ctype,3> b = triPoints[2] - triPoints[0]; StaticVector<ctype,3> c = a.cross(b); c.normalize(); StaticVector<ctype,3> x = p - triPoints[0]; // write x in the new base (Cramer's rule) StaticMatrix<ctype,3> numerator(a, b, c); StaticMatrix<ctype,3> alphaMat(x, b, c); StaticMatrix<ctype,3> betaMat(a, x, c); StaticMatrix<ctype,3> gammaMat(a, b, x); ctype alpha = alphaMat.det()/numerator.det(); ctype beta = betaMat.det()/numerator.det(); ctype gamma = gammaMat.det()/numerator.det(); // check whether orthogonal projection onto the ab plane is in triangle bool isIn = alpha>=0 && beta>=0 && (1-alpha-beta)>=0; if (isIn && fabs(gamma)<bestDist){ // printf("a(%1.2f %1.2f %1.2f) b(%1.2f %1.2f %1.2f) c(%1.2f %1.2f %1.2f) x(%1.2f %1.2f %1.2f)\n", // a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, x.x, x.y, x.z); // printf("tri: %d, alpha = %f, beta = %f, gamma = %f\n", j, alpha, beta, gamma); bestDist = fabs(gamma); } } // check point against edges for (i=0; i<size(); i++){ for (j=0; j<3; j++){ const DomainTriangle<ctype>& cT = par->triangles(triangles[i]); StaticVector<ctype,3> from = par->vertices(cT.vertices[j]); StaticVector<ctype,3> to = par->vertices(cT.vertices[(j+1)%3]); StaticVector<ctype,3> edge = to - from; ctype projectLength = edge.dot(p - from)/edge.length(); StaticVector<ctype,3> projection = edge/edge.length() * projectLength; ctype orthoDist = ((p-from) - projection).length(); if (projectLength>=0 && projectLength<=edge.length() && orthoDist<bestDist) bestDist = orthoDist; } } // check point against vertices for (i=0; i<size(); i++){ for (j=0; j<3; j++){ ctype dist = (p - par->vertices(par->triangles(triangles[i]).vertices[j])).length(); if (dist < bestDist){ bestDist = dist; } } } return bestDist; }