TEST(ReachabilitySphere, fitCylinder_2)
{
    Capability cylinder1(CYLINDER_2, 90.0, 90.0, 20.0);
    
    ReachabilitySphere sphere = createReachabilitySphereFromCapability(cylinder1, 200);
    
    // convert phi and theta to coordinates
    double phiInRad = 90.0 * M_PI / 180.0;
    double thetaInRad = 90.0 * M_PI / 180.0;

    Vector axis;
    axis.x = sin(thetaInRad) * cos(phiInRad);
    axis.y = sin(thetaInRad) * sin(phiInRad);
    axis.z = cos(thetaInRad);
    
    std::pair<double, double> angleAndSFE = sphere.fitCylinder_2(axis);
    ASSERT_TRUE(angleAndSFE.first < 20.01);
    ASSERT_TRUE(angleAndSFE.first > 19.0);
    ASSERT_EQ(angleAndSFE.second, 0.0);


    Capability cylinder2(CYLINDER_2, 320.0, 35.0, 40.0);
    
    sphere = createReachabilitySphereFromCapability(cylinder2, 200);
    
    // convert phi and theta to coordinates
    phiInRad = 320.0 * M_PI / 180.0;
    thetaInRad = 35.0 * M_PI / 180.0;

    axis.x = sin(thetaInRad) * cos(phiInRad);
    axis.y = sin(thetaInRad) * sin(phiInRad);
    axis.z = cos(thetaInRad);
    
    angleAndSFE = sphere.fitCylinder_2(axis);
    ASSERT_TRUE(angleAndSFE.first < 40.01 && angleAndSFE.first > 39.0);
    ASSERT_EQ(angleAndSFE.second, 0.0);


    // check that cylinder_1 is matched too if axis points to opposite direction
    Capability cylinder3(CYLINDER_2, 0.0, 0.0, 20.0);
    
    sphere = createReachabilitySphereFromCapability(cylinder3, 200);
    
    // convert phi and theta to coordinates
    phiInRad = 0.0 * M_PI / 180.0;
    thetaInRad = 180.0 * M_PI / 180.0;

    axis.x = sin(thetaInRad) * cos(phiInRad);
    axis.y = sin(thetaInRad) * sin(phiInRad);
    axis.z = cos(thetaInRad);
    
    angleAndSFE = sphere.fitCylinder_2(axis);
    ASSERT_TRUE(angleAndSFE.first < 20.0);
    ASSERT_EQ(angleAndSFE.second, 0.0);


    // check if SFE grows if axis is not alligned correctly
    Capability cylinder4(CYLINDER_2, 0.0, 0.0, 20.0);
    
    sphere = createReachabilitySphereFromCapability(cylinder4, 200);
    
    // convert phi and theta to coordinates
    phiInRad = 0.0 * M_PI / 180.0;
    thetaInRad = 10.0 * M_PI / 180.0;

    axis.x = sin(thetaInRad) * cos(phiInRad);
    axis.y = sin(thetaInRad) * sin(phiInRad);
    axis.z = cos(thetaInRad);
    
    angleAndSFE = sphere.fitCylinder_2(axis);
    ASSERT_TRUE(angleAndSFE.second > 0.0);
}
Esempio n. 2
0
INT WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, INT )
{
    srand( static_cast<unsigned>( time(NULL) ) );
    
    SkinningVertex * cylinder_vertices = NULL;
    Index * cylinder_indices = NULL;
    Vertex * tesselated_vertices = NULL;
    Index * tesselated_indices = NULL;
    try
    {
        Application app;

        VertexShader skinning_shader(app.get_device(), SKINNING_VERTEX_DECL_ARRAY, SKINNING_SHADER_FILENAME);
        VertexShader morphing_shader(app.get_device(), VERTEX_DECL_ARRAY, MORPHING_SHADER_FILENAME);
        
        // -------------------------- C y l i n d e r -----------------------

        cylinder_vertices = new SkinningVertex[CYLINDER_VERTICES_COUNT];
        cylinder_indices = new Index[CYLINDER_INDICES_COUNT];

        float height = 2.0f;
        cylinder( 0.7f, height,
                  colors, colors_count,
                  cylinder_vertices, cylinder_indices );

        SkinningModel cylinder1(app.get_device(),
                                D3DPT_TRIANGLESTRIP,
                                skinning_shader,
                                cylinder_vertices,
                                CYLINDER_VERTICES_COUNT,
                                cylinder_indices,
                                CYLINDER_INDICES_COUNT,
                                CYLINDER_INDICES_COUNT - 2,
                                D3DXVECTOR3(0.5f, 0.5f, -height/2),
                                D3DXVECTOR3(0,0,0),
                                D3DXVECTOR3(0,0,-1));

        height = 2.3f;
        cylinder( 0.3f, height,
                  &SECOND_CYLINDER_COLOR, 1,
                  cylinder_vertices, cylinder_indices );

        SkinningModel cylinder2(app.get_device(),
                                D3DPT_TRIANGLESTRIP,
                                skinning_shader,
                                cylinder_vertices,
                                CYLINDER_VERTICES_COUNT,
                                cylinder_indices,
                                CYLINDER_INDICES_COUNT,
                                CYLINDER_INDICES_COUNT - 2,
                                D3DXVECTOR3(-1.0f, 0.5f, height/2),
                                D3DXVECTOR3(D3DX_PI,0,-D3DX_PI/4),
                                D3DXVECTOR3(0,0,1));

        
        // -------------------------- P y r a m i d -----------------------
        const Index PLANES_PER_PYRAMID = 8;
        const D3DXVECTOR3 normal_up(0,0,1);
        const Vertex pyramid_vertices[]=
        {
            Vertex(D3DXVECTOR3(  0.5f, -0.5f,  0.00f ),normal_up),
            Vertex(D3DXVECTOR3( -0.5f, -0.5f,  0.00f ),normal_up),
            Vertex(D3DXVECTOR3( -0.5f,  0.5f,  0.00f ),normal_up),
            Vertex(D3DXVECTOR3(  0.5f,  0.5f,  0.00f ),normal_up),
            Vertex(D3DXVECTOR3(  0.0f,  0.0f,  0.7071f ),normal_up),
            Vertex(D3DXVECTOR3(  0.0f,  0.0f, -0.7071f ),normal_up),
        };
        const Index pyramid_indices[PLANES_PER_PYRAMID*VERTICES_PER_TRIANGLE] =
        {
            0, 4, 3,
            3, 4, 2,
            2, 4, 1,
            1, 4, 0,

            0, 3, 5,
            3, 2, 5,
            2, 1, 5,
            1, 0, 5,
        };

        const Index ALL_TESSELATED_VERTICES_COUNT = PLANES_PER_PYRAMID*TESSELATED_VERTICES_COUNT; // per 8 tessellated triangles
        const DWORD ALL_TESSELATED_INDICES_COUNT = PLANES_PER_PYRAMID*TESSELATED_INDICES_COUNT; // per 8 tessellated triangles

        tesselated_vertices = new Vertex[ALL_TESSELATED_VERTICES_COUNT];
        tesselated_indices = new Index[ALL_TESSELATED_INDICES_COUNT];

        for( DWORD i = 0; i < PLANES_PER_PYRAMID; ++i )
        {
            tessellate( pyramid_vertices, pyramid_indices, i*VERTICES_PER_TRIANGLE,
                        &tesselated_vertices[i*TESSELATED_VERTICES_COUNT], i*TESSELATED_VERTICES_COUNT,
                        &tesselated_indices[i*TESSELATED_INDICES_COUNT], SPHERE_COLOR );
        }
        
        MorphingModel pyramid( app.get_device(),
                               D3DPT_TRIANGLELIST,
                               morphing_shader,
                               tesselated_vertices,
                               ALL_TESSELATED_VERTICES_COUNT,
                               tesselated_indices,
                               ALL_TESSELATED_INDICES_COUNT,
                               ALL_TESSELATED_INDICES_COUNT/VERTICES_PER_TRIANGLE,
                               D3DXVECTOR3(0, -1.3f, -0.2f),
                               D3DXVECTOR3(0,0,0),
                               0.7071f);

        app.add_model(cylinder1);
        app.add_model(cylinder2);
        app.add_model(pyramid);
        app.run();
        delete_array(&tesselated_indices);
        delete_array(&tesselated_vertices);
        delete_array(&cylinder_indices);
        delete_array(&cylinder_vertices);
    }
    catch(RuntimeError &e)
    {
        delete_array(&tesselated_indices);
        delete_array(&tesselated_vertices);
        delete_array(&cylinder_indices);
        delete_array(&cylinder_vertices);
        const TCHAR *MESSAGE_BOX_TITLE = _T("Lighting error!");
        MessageBox(NULL, e.message(), MESSAGE_BOX_TITLE, MB_OK | MB_ICONERROR);
        return -1;
    }
    return 0;
}
TEST(ReachabilitySphere, getPrincipalComponents)
{
    ReachabilitySphere sphere;
    std::vector<Vector> vectors;
    std::vector<Vector> components;

    // a line in x direction should give the main principal component lying in x direction
    vectors.push_back(Vector(0.0, 0.0, 0.0));
    vectors.push_back(Vector(1.0, 0.0, 0.0));
    vectors.push_back(Vector(2.0, 0.0, 0.0));
    vectors.push_back(Vector(3.0, 0.0, 0.0));
    
    components = sphere.getPrincipalComponents(vectors);

    ASSERT_TRUE(components[2].x == 1.0);
    ASSERT_TRUE(components[2].y == 0.0);
    ASSERT_TRUE(components[2].z == 0.0);

    vectors.clear();

    // a line in y direction should give the main principal component lying in y direction
    vectors.push_back(Vector(0.0, 0.0, 0.0));
    vectors.push_back(Vector(0.0, 1.0, 0.0));
    vectors.push_back(Vector(0.0, 2.0, 0.0));
    vectors.push_back(Vector(0.0, 3.0, 0.0));
    
    components = sphere.getPrincipalComponents(vectors);

    ASSERT_TRUE(components[2].x == 0.0);
    ASSERT_TRUE(components[2].y == 1.0);
    ASSERT_TRUE(components[2].z == 0.0);

    vectors.clear();

    // a line in z direction should give the main principal component lying in z direction
    vectors.push_back(Vector(0.0, 0.0, 0.0));
    vectors.push_back(Vector(0.0, 0.0, 1.0));
    vectors.push_back(Vector(0.0, 0.0, 2.0));
    vectors.push_back(Vector(0.0, 0.0, 3.0));
    
    components = sphere.getPrincipalComponents(vectors);

    ASSERT_TRUE(components[2].x == 0.0);
    ASSERT_TRUE(components[2].y == 0.0);
    ASSERT_TRUE(components[2].z == 1.0);

    vectors.clear();

    // filling just x and y directions should give the least principal component in z direction
    vectors.push_back(Vector(1.0, 2.0, 0.0));
    vectors.push_back(Vector(2.0, 1.0, 0.0));
    vectors.push_back(Vector(1.0, 0.0, 0.0));
    vectors.push_back(Vector(0.0, 1.0, 0.0));
    
    components = sphere.getPrincipalComponents(vectors);

    ASSERT_TRUE(components[0].x == 0.0);
    ASSERT_TRUE(components[0].y == 0.0);
    ASSERT_TRUE(components[0].z == 1.0);

    vectors.clear();

    // filling just y and z directions should give the least principal component in x direction
    vectors.push_back(Vector(0.0, 2.0, 0.0));
    vectors.push_back(Vector(0.0, 1.0, 2.0));
    vectors.push_back(Vector(0.0, 0.0, 1.0));
    vectors.push_back(Vector(0.0, 1.0, 1.0));
    
    components = sphere.getPrincipalComponents(vectors);

    ASSERT_TRUE(components[0].x == 1.0);
    ASSERT_TRUE(components[0].y == 0.0);
    ASSERT_TRUE(components[0].z == 0.0);

    vectors.clear();

    // filling just x and z directions should give the least principal component in y direction
    vectors.push_back(Vector(1.0, 0.0, 0.0));
    vectors.push_back(Vector(2.0, 0.0, 2.0));
    vectors.push_back(Vector(2.0, 0.0, 1.0));
    vectors.push_back(Vector(0.0, 0.0, 1.0));
    
    components = sphere.getPrincipalComponents(vectors);

    ASSERT_TRUE(components[0].x == 0.0);
    ASSERT_TRUE(components[0].y == 1.0);
    ASSERT_TRUE(components[0].z == 0.0);

    vectors.clear();

    // a line in x-y direction should give the main principal component lying in x-y direction
    vectors.push_back(Vector(0.0, 0.0, 0.0));
    vectors.push_back(Vector(1.0, 1.0, 0.0));
    vectors.push_back(Vector(2.0, 2.0, 0.0));
    vectors.push_back(Vector(3.0, 3.0, 0.0));
    
    components = sphere.getPrincipalComponents(vectors);

    ASSERT_TRUE(fuzzyEquals(std::abs(components[2].x), 0.707106781));
    ASSERT_TRUE(fuzzyEquals(std::abs(components[2].y), 0.707106781));
    ASSERT_TRUE(components[2].z == 0.0);


    // test Capability of type cone
    Capability cone(CONE, 70.0, 55.0, 35.0);
    
    sphere = createReachabilitySphereFromCapability(cone, 400);

    components = sphere.getPrincipalComponents(sphere._reachableDirections);

    // test phi
    ASSERT_TRUE(atan2(components[0].y, components[0].x) * 180.0 / M_PI < 72.0);
    ASSERT_TRUE(atan2(components[0].y, components[0].x) * 180.0 / M_PI > 68.0);

    // test theta
    ASSERT_TRUE(acos(components[0].z) * 180.0 / M_PI < 56.0);
    ASSERT_TRUE(acos(components[0].z) * 180.0 / M_PI > 54.0);


    // test Capability of type cylinder_1
    Capability cylinder1(CYLINDER_1, 70.0, 55.0, 35.0);
    
    sphere = createReachabilitySphereFromCapability(cylinder1, 400);

    components = sphere.getPrincipalComponents(sphere._reachableDirections);

    // test phi
    ASSERT_TRUE(atan2(components[2].y, components[2].x) * 180.0 / M_PI < 72.0);
    ASSERT_TRUE(atan2(components[2].y, components[2].x) * 180.0 / M_PI > 68.0);

    // test theta
    ASSERT_TRUE(acos(components[2].z) * 180.0 / M_PI < 56.0);
    ASSERT_TRUE(acos(components[2].z) * 180.0 / M_PI > 54.0);


    // test Capability of type cylinder_2
    Capability cylinder2(CYLINDER_2, 70.0, 55.0, 35.0);
    
    sphere = createReachabilitySphereFromCapability(cylinder2, 400);

    components = sphere.getPrincipalComponents(sphere._reachableDirections);

    // test phi
    ASSERT_TRUE(atan2(components[0].y, components[0].x) * 180.0 / M_PI < 72.0);
    ASSERT_TRUE(atan2(components[0].y, components[0].x) * 180.0 / M_PI > 68.0);

    // test theta
    ASSERT_TRUE(acos(components[0].z) * 180.0 / M_PI < 56.0);
    ASSERT_TRUE(acos(components[0].z) * 180.0 / M_PI > 54.0);
}