bool EdgeLengthQualityMetric::evaluate_vertex(PatchData &pd, MsqVertex* vert,
                                             double &fval, MsqError &err)
{
  fval=0.0;
  size_t this_vert = pd.get_vertex_index(vert);
  size_t other_vert;
  vector<size_t> adj_verts;
  Vector3D edg;
  pd.get_adjacent_vertex_indices(this_vert,adj_verts,err);  MSQ_ERRZERO(err);
  int num_sample_points=adj_verts.size();
  double *metric_values=new double[num_sample_points];
  MsqVertex* verts = pd.get_vertex_array(err);  MSQ_ERRZERO(err);
  int point_counter=0;
  while(!adj_verts.empty()){
    other_vert=adj_verts.back();
    adj_verts.pop_back();
    edg[0]=verts[this_vert][0]-verts[other_vert][0];
    edg[1]=verts[this_vert][1]-verts[other_vert][1];
    edg[2]=verts[this_vert][2]-verts[other_vert][2];    
    metric_values[point_counter]=edg.length();
    ++point_counter;
  }
  fval=average_metrics(metric_values,num_sample_points,err);  MSQ_ERRZERO(err);
  delete[] metric_values;
  
  return true;
  
}
Example #2
0
void CircleDomain::position_from_length( const double from_here[3],
                                         double length,
                                         double result_point[3],
                                         MsqError& )
{
  Vector3D b = Vector3D(from_here) - mGeom.center();
  Vector3D vy = mGeom.normal() * b;
  Vector3D vx = vy * mGeom.normal();
  double angle = length / mGeom.radius();
  double x = std::cos( angle );
  double y = std::sin( angle );
  vy *= y/vy.length();
  vx *= x/vx.length();
  Vector3D result = vx + vy;
  result *= mGeom.radius();
  result += mGeom.center();
  result.get_coordinates( result_point );
}
Example #3
0
double CMesh::GetEdgeLen(UINT iEdge)
{
	CVertex* pVertex[2];
	pVertex[0]=&(m_pVertex[m_pEdge[iEdge].m_iVertex[0]]);
	pVertex[1]=&(m_pVertex[m_pEdge[iEdge].m_iVertex[1]]);
		
	//get the vector
	Vector3D v = pVertex[0]->m_vPosition-pVertex[1]->m_vPosition;
	return v.length();
}
void BoundedCylinderDomain::evaluate( double t, 
                                      const Vector3D& point,
                                      Vector3D& closest,
                                      Vector3D& normal ) const
{
  const double EPSILON = std::numeric_limits<double>::epsilon();
  double t2 = axis() % (point - center());
  const Vector3D circ_center = center() + t * axis();
  const Vector3D axis_point = center() + t2 * axis();
  
  normal = point - axis_point;
  const double len = normal.length();
  if (len < EPSILON)
  {
    this->CylinderDomain::evaluate( 0, axis_point, closest, normal );
  }
  else
  {
    normal /= len;
    closest = circ_center + radius() * normal;
  }
}
	bool Vector3D::operator >(const Vector3D i_other) const
	{
		return (length() > i_other.length() ? true : false);
	}
bool IdealWeightInverseMeanRatio::evaluate( PatchData& pd,
        size_t handle,
        double& m,
        MsqError& err )
{
    const MsqMeshEntity* e = &pd.element_by_index(handle);
    EntityTopology topo = e->get_element_type();

    const MsqVertex *vertices = pd.get_vertex_array(err);
    MSQ_ERRZERO(err);
    const size_t *v_i = e->get_vertex_index_array();

    Vector3D n;			// Surface normal for 2D objects

    // Prism and Hex element descriptions
    static const int locs_pri[6][4] = {{0, 1, 2, 3}, {1, 2, 0, 4},
        {2, 0, 1, 5}, {3, 5, 4, 0},
        {4, 3, 5, 1}, {5, 4, 3, 2}
    };
    static const int locs_hex[8][4] = {{0, 1, 3, 4}, {1, 2, 0, 5},
        {2, 3, 1, 6}, {3, 0, 2, 7},
        {4, 7, 5, 0}, {5, 4, 6, 1},
        {6, 5, 7, 2}, {7, 6, 4, 3}
    };

    const Vector3D d_con(1.0, 1.0, 1.0);

    int i;

    m = 0.0;
    bool metric_valid = false;
    switch(topo) {
    case TRIANGLE:
        pd.get_domain_normal_at_element(e, n, err);
        MSQ_ERRZERO(err);
        n = n / n.length();		// Need unit normal
        mCoords[0] = vertices[v_i[0]];
        mCoords[1] = vertices[v_i[1]];
        mCoords[2] = vertices[v_i[2]];
        metric_valid = m_fcn_2e(m, mCoords, n, a2Con, b2Con, c2Con);
        if (!metric_valid) return false;
        break;

    case QUADRILATERAL:
        pd.get_domain_normal_at_element(e, n, err);
        MSQ_ERRZERO(err);
        n = n / n.length();	// Need unit normal
        for (i = 0; i < 4; ++i) {
            mCoords[0] = vertices[v_i[locs_hex[i][0]]];
            mCoords[1] = vertices[v_i[locs_hex[i][1]]];
            mCoords[2] = vertices[v_i[locs_hex[i][2]]];
            metric_valid = m_fcn_2i(mMetrics[i], mCoords, n,
                                    a2Con, b2Con, c2Con, d_con);
            if (!metric_valid) return false;
        }
        m = average_metrics(mMetrics, 4, err);
        break;

    case TETRAHEDRON:
        mCoords[0] = vertices[v_i[0]];
        mCoords[1] = vertices[v_i[1]];
        mCoords[2] = vertices[v_i[2]];
        mCoords[3] = vertices[v_i[3]];
        metric_valid = m_fcn_3e(m, mCoords, a3Con, b3Con, c3Con);
        if (!metric_valid) return false;
        break;

    case PYRAMID:
        for (i = 0; i < 4; ++i) {
            mCoords[0] = vertices[v_i[ i     ]];
            mCoords[1] = vertices[v_i[(i+1)%4]];
            mCoords[2] = vertices[v_i[(i+3)%4]];
            mCoords[3] = vertices[v_i[ 4     ]];
            metric_valid = m_fcn_3p(mMetrics[i], mCoords, a3Con, b3Con, c3Con);
            if (!metric_valid) return false;
        }
        m = average_metrics(mMetrics, 4, err);
        MSQ_ERRZERO(err);
        break;

    case PRISM:
        for (i = 0; i < 6; ++i) {
            mCoords[0] = vertices[v_i[locs_pri[i][0]]];
            mCoords[1] = vertices[v_i[locs_pri[i][1]]];
            mCoords[2] = vertices[v_i[locs_pri[i][2]]];
            mCoords[3] = vertices[v_i[locs_pri[i][3]]];
            metric_valid = m_fcn_3w(mMetrics[i], mCoords, a3Con, b3Con, c3Con);
            if (!metric_valid) return false;
        }
        m = average_metrics(mMetrics, 6, err);
        MSQ_ERRZERO(err);
        break;

    case HEXAHEDRON:
        for (i = 0; i < 8; ++i) {
            mCoords[0] = vertices[v_i[locs_hex[i][0]]];
            mCoords[1] = vertices[v_i[locs_hex[i][1]]];
            mCoords[2] = vertices[v_i[locs_hex[i][2]]];
            mCoords[3] = vertices[v_i[locs_hex[i][3]]];
            metric_valid = m_fcn_3i(mMetrics[i], mCoords,
                                    a3Con, b3Con, c3Con, d_con);
            if (!metric_valid) return false;
        }
        m = average_metrics(mMetrics, 8, err);
        MSQ_ERRZERO(err);
        break;

    default:
        MSQ_SETERR(err)(MsqError::UNSUPPORTED_ELEMENT,
                        "Element type (%d) not supported in IdealWeightInverseMeanRatio",
                        (int)topo);
        return false;
    } // end switch over element type
    return true;
}
bool IdealWeightInverseMeanRatio::evaluate_with_Hessian( PatchData& pd,
        size_t handle,
        double& m,
        std::vector<size_t>& indices,
        std::vector<Vector3D>& g,
        std::vector<Matrix3D>& h,
        MsqError& err )
{
    const MsqMeshEntity* e = &pd.element_by_index(handle);
    EntityTopology topo = e->get_element_type();

    if (!analytical_average_hessian() &&
            topo != TRIANGLE &&
            topo != TETRAHEDRON) {
        static bool print = true;
        if (print) {
            MSQ_DBGOUT(1) << "Analyical gradient not available for selected averaging scheme. "
                          << "Using (possibly much slower) numerical approximation of gradient"
                          << " of quality metric. " << std::endl;
            print = false;
        }
        return QualityMetric::evaluate_with_Hessian( pd, handle, m, indices, g, h, err );
    }

    const MsqVertex *vertices = pd.get_vertex_array(err);
    MSQ_ERRZERO(err);
    const size_t *v_i = e->get_vertex_index_array();


    Vector3D n;			// Surface normal for 2D objects

    // Prism and Hex element descriptions
    static const int locs_pri[6][4] = {{0, 1, 2, 3}, {1, 2, 0, 4},
        {2, 0, 1, 5}, {3, 5, 4, 0},
        {4, 3, 5, 1}, {5, 4, 3, 2}
    };
    static const int locs_hex[8][4] = {{0, 1, 3, 4}, {1, 2, 0, 5},
        {2, 3, 1, 6}, {3, 0, 2, 7},
        {4, 7, 5, 0}, {5, 4, 6, 1},
        {6, 5, 7, 2}, {7, 6, 4, 3}
    };

    const Vector3D d_con(1.0, 1.0, 1.0);

    int i;

    bool metric_valid = false;
    const uint32_t fm = fixed_vertex_bitmap( pd, e, indices );

    m = 0.0;

    switch(topo) {
    case TRIANGLE:
        pd.get_domain_normal_at_element(e, n, err);
        MSQ_ERRZERO(err);
        n /= n.length();		// Need unit normal
        mCoords[0] = vertices[v_i[0]];
        mCoords[1] = vertices[v_i[1]];
        mCoords[2] = vertices[v_i[2]];
        g.resize(3);
        h.resize(6);
        if (!h_fcn_2e(m, &g[0], &h[0], mCoords, n, a2Con, b2Con, c2Con)) return false;
        break;

    case QUADRILATERAL:
        pd.get_domain_normal_at_element(e, n, err);
        MSQ_ERRZERO(err);
        n /= n.length();	// Need unit normal
        for (i = 0; i < 4; ++i) {
            mCoords[0] = vertices[v_i[locs_hex[i][0]]];
            mCoords[1] = vertices[v_i[locs_hex[i][1]]];
            mCoords[2] = vertices[v_i[locs_hex[i][2]]];
            if (!h_fcn_2i(mMetrics[i], mGradients+3*i, mHessians+6*i, mCoords, n,
                          a2Con, b2Con, c2Con, d_con)) return false;
        }

        g.resize(4);
        h.resize(10);
        m = average_corner_hessians( QUADRILATERAL, fm, 4,
                                     mMetrics, mGradients, mHessians,
                                     &g[0], &h[0], err );
        MSQ_ERRZERO( err );
        break;

    case TETRAHEDRON:
        mCoords[0] = vertices[v_i[0]];
        mCoords[1] = vertices[v_i[1]];
        mCoords[2] = vertices[v_i[2]];
        mCoords[3] = vertices[v_i[3]];
        g.resize(4);
        h.resize(10);
        metric_valid = h_fcn_3e(m, &g[0], &h[0], mCoords, a3Con, b3Con, c3Con);
        if (!metric_valid) return false;
        break;

    case PYRAMID:
        for (i = 0; i < 4; ++i) {
            mCoords[0] = vertices[v_i[ i     ]];
            mCoords[1] = vertices[v_i[(i+1)%4]];
            mCoords[2] = vertices[v_i[(i+3)%4]];
            mCoords[3] = vertices[v_i[ 4     ]];
            metric_valid = h_fcn_3p(mMetrics[i], mGradients+4*i,
                                    mHessians+10*i, mCoords, a3Con, b3Con, c3Con);

            if (!metric_valid) return false;
        }

        g.resize(5);
        h.resize(15);
        m = average_corner_hessians( PYRAMID, fm, 4,
                                     mMetrics, mGradients, mHessians,
                                     &g[0], &h[0], err );
        MSQ_ERRZERO( err );
        break;

    case PRISM:
        for (i = 0; i < 6; ++i) {
            mCoords[0] = vertices[v_i[locs_pri[i][0]]];
            mCoords[1] = vertices[v_i[locs_pri[i][1]]];
            mCoords[2] = vertices[v_i[locs_pri[i][2]]];
            mCoords[3] = vertices[v_i[locs_pri[i][3]]];
            if (!h_fcn_3w(mMetrics[i], mGradients+4*i, mHessians+10*i, mCoords,
                          a3Con, b3Con, c3Con)) return false;
        }

        g.resize(6);
        h.resize(21);
        m = average_corner_hessians( PRISM, fm, 6,
                                     mMetrics, mGradients, mHessians,
                                     &g[0], &h[0], err );
        MSQ_ERRZERO( err );
        break;

    case HEXAHEDRON:
        for (i = 0; i < 8; ++i) {
            mCoords[0] = vertices[v_i[locs_hex[i][0]]];
            mCoords[1] = vertices[v_i[locs_hex[i][1]]];
            mCoords[2] = vertices[v_i[locs_hex[i][2]]];
            mCoords[3] = vertices[v_i[locs_hex[i][3]]];
            if (!h_fcn_3i(mMetrics[i], mGradients+4*i, mHessians+10*i, mCoords,
                          a3Con, b3Con, c3Con, d_con)) return false;
        }

        g.resize(8);
        h.resize(36);
        m = average_corner_hessians( HEXAHEDRON, fm, 8,
                                     mMetrics, mGradients, mHessians,
                                     &g[0], &h[0], err );
        MSQ_ERRZERO( err );
        break;

    default:
        MSQ_SETERR(err)(MsqError::UNSUPPORTED_ELEMENT,
                        "Element type (%d) not supported in IdealWeightInverseMeanRatio",
                        (int)topo);
        return false;
    } // end switch over element type

    remove_fixed_gradients( topo, fm, g );
    remove_fixed_hessians( topo, fm, h );
    return true;
}
Example #8
0
void a4_render(// What to render
               SceneNode* root,
               // Where to output the image
               const std::string& filename,
               // Image size
               int width, int height,
               // Viewing parameters
               const Point3D& eye, const Vector3D& view,
               const Vector3D& up, double fov,
               // Lighting parameters
               const Colour& ambient,
               const std::list<Light*>& lights
               )
{
    // Fill in raytracing code here.
    Image img(width, height, 3);
    Matrix4x4 inv_transf;
    //pinhole camera
    Vector3D m_cx = (view.cross(up));
    m_cx.normalize();
    Vector3D m_cy = (-up);

    double m_fovrad = (fov*M_PI)/360.0;
    double m_cw = tan(m_fovrad);
    double a =(double(width)/double(height));
    double m_ch = m_cw;

    //for percent display
    float done = 0;
#pragma omp parallel for default(shared) reduction(+:done) schedule(guided)
    for (int y = 0; y < height; y++) {
        done = done + 1.0f;
        display_percentage( done, (float)height);
        for (int x = 0; x < width; x++) {
            //background color
            // Red: increasing from top to bottom
            double red = (double)y / height;
            // Green: increasing from top and bottom to middle
            double green = ((red <= 0.5) ? 2.0*red : (2.0 - 2.0*red));
            // Blue: decreasing from top to bottom
            double blue = 1.0 - red;
            Colour back(red,green,blue);
            //antialiasing  http://www.codermind.com/articles/Raytracer-in-C++-Part-II-Specularity-post-processing.html
            double sampleRatio= 0.25;
            Colour aux(0.0, 0.0, 0.0);
            for (double fragmentx = double(x) ; fragmentx < x + 1.0; fragmentx += 0.5 )
                for (double fragmenty = double(y) ; fragmenty < y + 1.0; fragmenty += 0.5 )
                {
                    Vector3D m_raydir;
                    //get primary ray direction
                    m_raydir = view + (fragmentx / (double(width))*2.0 -1.0 )*m_cw*a*m_cx + ((fragmenty) / (double(height))*2.0 - 1.0) * m_ch*m_cy;
                    m_raydir.normalize();
                    //m_raydir = Vector3D(0.0,0.0,-1.0);
                    Ray r(eye,m_raydir);
                    //Ray r(Point3D(x,y,800),m_raydir);
                    double coef = 1.0;
                    int level = 0;
                    bool hit = false;
                    Colour tmp(0.0, 0.0, 0.0);
                    do{
                        // find the closest intersection
                        Intersection closest_isect;
                        hit = root->closest_intersect(r,closest_isect,inv_transf);
                        //if(!hit) cout<< "fail hit"<< endl;
                        if(hit){
                            //cout<< "success hit"<< endl;
                            // put color to pixel
                            Colour diffuse(0.0, 0.0, 0.0);
                            Colour specular(0.0, 0.0, 0.0);
                            Ray reflected_ray;//reflected ray
                            reflected_ray.origin()= closest_isect.position();

                            for (std::list<Light*>::const_iterator cl = lights.begin(); cl != lights.end(); ++cl){

                                Vector3D L = (*cl)->position - closest_isect.position();
                                double light_dist = L.length();
                                if((L.dot(closest_isect.normal())) <= 0.0 || light_dist < 0.0)// test if the point if lighted
                                    continue;
                                L.normalize();
                                reflected_ray.direction()=L;

                                // attenuation factor
                                double fatt = 1.0/((*cl)->falloff[0]+ (*cl)->falloff[1]*light_dist
                                                   + (*cl)->falloff[2]*light_dist*light_dist);
                                coef = fatt;
                                if(coef < double(1e-6)) break;

                                // test if point is in shadow
                                bool in_shadow = false;
                                Intersection aux_isect;
                                if(root->closest_intersect(reflected_ray,aux_isect,inv_transf,light_dist))
                                    in_shadow = true;

                                //ilumination
                                if(!in_shadow){
                                    double lambert = reflected_ray.direction().dot(closest_isect.normal())*fatt;
                                    diffuse = diffuse + (lambert*(*cl)->colour)*closest_isect.mtrl()->get_diffuse();
                                    // reflection by blinn-phong model reference:http://www.codermind.com/
                                    Vector3D blinnDir = reflected_ray.direction() - r.direction();
                                    double temp = blinnDir.length2();
                                    if (temp != 0.0 )
                                    {
                                        blinnDir.normalize();
                                        double blinnTerm = max(blinnDir.dot(closest_isect.normal()), 0.0);
                                        blinnTerm = pow(blinnTerm ,closest_isect.mtrl()->get_shininess())*fatt;

                                        specular =specular + blinnTerm*closest_isect.mtrl()->get_specular()*(*cl)->colour;
                                    }
                                }
                            }
                            tmp = tmp + ambient*closest_isect.mtrl()->get_diffuse() + diffuse + specular;
                            if(closest_isect.mtrl()->get_shininess() < eps)
                                break;
                            double reflet = 2.0*(r.direction().dot(closest_isect.normal()));
                            r.origin() = closest_isect.position() + eps*closest_isect.normal();
                            r.direction() = (r.direction() - reflet * closest_isect.normal());
                            r.direction().normalize();
                            level++;
                        }
                    }while((coef > double(1e-6)) && level < 5 && hit);

                    aux =aux + sampleRatio*tmp;
                }
            if(aux.R()!=0.0 || aux.G()!= 0.0 || aux.B()!= 0.0)
                back = aux;

            img(x, y, 0) = back.R();
            img(x, y, 1) =back.G();
            img(x, y, 2) = back.B();
        }
    }

    std::cerr << "Stub: a4_render(" << root << ",\n     "
              << filename << ", " << width << ", " << height << ",\n     "
              << eye << ", " << view << ", " << up << ", " << fov << ",\n     "
              << ambient << ",\n     {";

    for (std::list<Light*>::const_iterator I = lights.begin(); I != lights.end(); ++I) {
        if (I != lights.begin()) std::cerr << ", ";
        std::cerr << **I;
    }
    std::cerr << "});" << std::endl;
    img.savePng(filename);
}
Example #9
0
// where v is normal to the plane, and w is the vector to the point
double BoundingBox::projection(const Vector3D &v, const Vector3D &w) const
{
	double dot = v.dot(w);
	dot = dot / v.length();
	return dot;
}