Esempio n. 1
0
template<class T> Tuple<Vector<T,2>,Vector<T,3>> Triangle<Vector<T,2>>::
closest_point(const Vector<T,2>& location) const
{
    TV closest;
    Vector<T,3> weights = barycentric_coordinates(location);
    // project closest point to the triangle if it's not already inside it
    if(weights.x<0){
        T a23=interpolation_fraction(simplex(X[1],X[2]),location); // Check edge X[1]--X[2]
        if(a23<0){
            if(weights.z<0){ // Closest point is on edge X[0]--X[1]
                T a12=clamp<T>(interpolation_fraction(simplex(X[0],X[1]),location),0,1);weights=Vector<T,3>(1-a12,a12,0);closest=weights.x*X[0]+weights.y*X[1];}
            else{weights=Vector<T,3>(0,1,0);closest=X[1];}} // Closest point is X[1]
        else if(a23>1){
            if(weights.y<0){ // Closest point is on edge X[0]--X[2]
                T a13=clamp<T>(interpolation_fraction(simplex(X[0],X[2]),location),0,1);weights=Vector<T,3>(1-a13,0,a13);closest=weights.x*X[0]+weights.z*X[2];}
            else{weights=Vector<T,3>(0,0,1);closest=X[2];}} // Closest point is X[2]
        else{weights=Vector<T,3>(0,1-a23,a23);closest=weights.y*X[1]+weights.z*X[2];}} // Closest point is on edge X[1]--X[2]
    else if(weights.y<0){
        T a13=interpolation_fraction(simplex(X[0],X[2]),location); // Check edge X[0]--X[2]
        if(a13<0){
            if(weights.z<0){ // Closest point is on edge X[0]--X[1]
                T a12=clamp<T>(interpolation_fraction(simplex(X[0],X[1]),location),0,1);weights=Vector<T,3>(1-a12,a12,0);closest=weights.x*X[0]+weights.y*X[1];}
            else{weights=Vector<T,3>(1,0,0);closest=X[0];}} // Closest point is X[0]
        else if(a13>1){weights=Vector<T,3>(0,0,1);closest=X[2];} // Closest point is X[2]
        else{weights=Vector<T,3>(1-a13,0,a13);closest=weights.x*X[0]+weights.z*X[2];}} // Closest point is on edge X[0]--X[2]
    else if(weights.z<0){ // Closest point is on edge X[0]--X[1]
        T a12=clamp<T>(interpolation_fraction(simplex(X[0],X[1]),location),0,1);weights=Vector<T,3>(1-a12,a12,0);closest=weights.x*X[0]+weights.y*X[1];}
    else
        closest=weights.x*X[0]+weights.y*X[1]+weights.z*X[2]; // Point is interior to the triangle
    return tuple(closest,weights);
}
Esempio n. 2
0
bool Triangle::intersect(const Ray& r, LocalGeometry& lgeo) {
    Mat4 TInv = this->transform.inverse();
    Vec3 dir = as_vec3(TInv*as_vec4(r.direction));
    Vec4 origin = TInv*r.origin;


    if (cross(dir, normal).is_zero())
        return false;

    double t = dot(as_vec3(origin-A), normal)/dot(dir, normal);

    if (t < 0.0)
        return false;
    else {
        Vec4 point = origin + (as_vec4(dir) * t);

        Vec3 bar_coords = barycentric_coordinates(A, B, C, point);

        double alpha = bar_coords.el(0);
        double beta = bar_coords.el(1);
        double gamma = bar_coords.el(2);

        if (alpha < 0.0 || beta < 0.0 || gamma < 0.0)
            return false;

        else {
            lgeo.normal = submatrix(transform).inverse().transpose() * normal;
            lgeo.point = transform * point;
            lgeo.geo = this;
            return true;
        }
    }
}
Esempio n. 3
0
            void compute_closest_points(const Vec3d& P, Vec3d& pa, Vec3d& pb){
                switch(size_){
                //If the simplex has 4 points, it means that the last point added,
                //most likely lies on the previous simplex, a triangle. We instead
                //use the last simplex to compute the closest points.
                case 4:{
                    const uchar* pos = p_pos[(bits_ ^ (1 << last_sb_))];
                    const Vec3d& aA = a_[pos[0]];
                    const Vec3d& aB = a_[pos[1]];
                    const Vec3d& aC = a_[pos[2]];
                    const Vec3d& bA = b_[pos[0]];
                    const Vec3d& bB = b_[pos[1]];
                    const Vec3d& bC = b_[pos[2]];

                    const Vec3d& A = p_[pos[0]];
                    const Vec3d& B = p_[pos[1]];
                    const Vec3d& C = p_[pos[2]];

                    auto bary = barycentric_coordinates(P, A, B, C);

                    pa = aA * bary[0] + aB * bary[1] + aC * bary[2];
                    pb = bA * bary[0] + bB * bary[1] + bC * bary[2];

                    break;
                }
                case 3:{
                    const uchar* pos = p_pos[(bits_ ^ (1 << last_sb_))];
                    const Vec3d& aA = a_[last_sb_];
                    const Vec3d& aB = a_[pos[0]];
                    const Vec3d& aC = a_[pos[1]];
                    const Vec3d& bA = b_[last_sb_];
                    const Vec3d& bB = b_[pos[0]];
                    const Vec3d& bC = b_[pos[1]];

                    const Vec3d& A = p_[last_sb_];
                    const Vec3d& B = p_[pos[0]];
                    const Vec3d& C = p_[pos[1]];

                    auto bary = barycentric_coordinates(P, A, B, C);

                    pa = aA * bary[0] + aB * bary[1] + aC * bary[2];
                    pb = bA * bary[0] + bB * bary[1] + bC * bary[2];

                    break;
                }
                case 2:{
                    const uchar* pos = p_pos[(bits_ ^ (1 << last_sb_))];
                    const Vec3d& aA = a_[last_sb_];
                    const Vec3d& aB = a_[pos[0]];
                    const Vec3d& bA = b_[last_sb_];
                    const Vec3d& bB = b_[pos[0]];
                    double u, v;
                    {
                        const Vec3d& A = p_[last_sb_];
                        const Vec3d& B = p_[pos[0]];

                        auto AB = B - A;
                        v = dot(AB, P - A) / AB.length2();
                        u = 1.0 - v;
                    }

                    pa = aA * u + aB * v;
                    pb = bA * u + bB * v;

                    break;
                }
                case 1:{
                    pa = a_[last_sb_];
                    pb = b_[last_sb_];
                    break;
                }
                default:
                break;
                }
            }