Beispiel #1
0
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;
}
Beispiel #2
0
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!"));

        }

    }

}
Beispiel #3
0
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!"));

        }

    }

}
Beispiel #4
0
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;
}