<commit_before>#include "catch.hpp"

#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/geometry/box2d.hpp>

#ifdef MAPNIK_USE_PROJ4
// proj4
#include <proj_api.h>
#endif

TEST_CASE("projection transform")
{

SECTION("Test bounding box transforms - 4326 to 3857")
{
    mapnik::projection proj_4326("+init=epsg:4326");
    mapnik::projection proj_3857("+init=epsg:3857");
    mapnik::proj_transform prj_trans(proj_4326, proj_3857);

    double minx = -45.0;
    double miny = 55.0;
    double maxx = -40.0;
    double maxy = 75.0;

    mapnik::box2d<double> bbox(minx, miny, maxx, maxy);

    prj_trans.forward(bbox);
    INFO(bbox.to_string());
    CHECK(bbox.minx() == Approx(-5009377.085697311));
    CHECK(bbox.miny() == Approx(7361866.1130511891));
    CHECK(bbox.maxx() == Approx(-4452779.631730943));
    CHECK(bbox.maxy() == Approx(12932243.1119920239));

    prj_trans.backward(bbox);
    CHECK(bbox.minx() == Approx(minx));
    CHECK(bbox.miny() == Approx(miny));
    CHECK(bbox.maxx() == Approx(maxx));
    CHECK(bbox.maxy() == Approx(maxy));

}

#if defined(MAPNIK_USE_PROJ4) && PJ_VERSION >= 480
SECTION("test pj_transform failure behavior")
{
    mapnik::projection proj_4269("+init=epsg:4269");
    mapnik::projection proj_3857("+init=epsg:3857");
    mapnik::proj_transform prj_trans(proj_4269, proj_3857);
    mapnik::proj_transform prj_trans2(proj_3857, proj_4269);

    auto proj_ctx0 = pj_ctx_alloc();
    REQUIRE( proj_ctx0 != nullptr );
    auto proj0 = pj_init_plus_ctx(proj_ctx0, proj_4269.params().c_str());
    REQUIRE( proj0 != nullptr );

    auto proj_ctx1 = pj_ctx_alloc();
    REQUIRE( proj_ctx1 != nullptr );
    auto proj1 = pj_init_plus_ctx(proj_ctx1, proj_3857.params().c_str());
    REQUIRE( proj1 != nullptr );

    // first test valid values directly against proj
    double x = -180.0;
    double y = -60.0;
    x *= DEG_TO_RAD;
    y *= DEG_TO_RAD;
    CHECK( x == Approx(-3.1415926536) );
    CHECK( y == Approx(-1.0471975512) );
    CHECK( 0 == pj_transform(proj0, proj1, 1, 0, &x, &y, nullptr) );
    CHECK( x == Approx(-20037508.3427892439) );
    CHECK( y == Approx(-8399737.8896366451) );

    // now test mapnik class
    double x0 = -180.0;
    double y0 = -60.0;
    CHECK( prj_trans.forward(&x0,&y0,nullptr,1,1) );
    CHECK( x0 == Approx(-20037508.3427892439) );
    CHECK( y0 == Approx(-8399737.8896366451) );
    double x1 = -180.0;
    double y1 = -60.0;
    CHECK( prj_trans2.backward(&x1,&y1,nullptr,1,1) );
    CHECK( x1 == Approx(-20037508.3427892439) );
    CHECK( y1 == Approx(-8399737.8896366451) );

    // longitude value outside the value range for mercator
    x = -181.0;
    y = -91.0;
    x *= DEG_TO_RAD;
    y *= DEG_TO_RAD;
    CHECK( x == Approx(-3.1590459461) );
    CHECK( y == Approx(-1.5882496193) );
    CHECK( 0 == pj_transform(proj0, proj1, 1, 0, &x, &y, nullptr) );
    CHECK( std::isinf(x) );
    CHECK( std::isinf(y) );

    // now test mapnik class
    double x2 = -181.0;
    double y2 = -91.0;
    CHECK( false == prj_trans.forward(&x2,&y2,nullptr,1,1) );
    CHECK( std::isinf(x2) );
    CHECK( std::isinf(y2) );
    double x3 = -181.0;
    double y3 = -91.0;
    CHECK( false == prj_trans2.backward(&x3,&y3,nullptr,1,1) );
    CHECK( std::isinf(x3) );
    CHECK( std::isinf(y3) );

    // cleanup
    pj_ctx_free(proj_ctx0);
    proj_ctx0 = nullptr;
    pj_free(proj0);
    proj0 = nullptr;
    pj_ctx_free(proj_ctx1);
    proj_ctx1 = nullptr;
    pj_free(proj1);
    proj1 = nullptr;
}

#endif

// Github Issue https://github.com/mapnik/mapnik/issues/2648
SECTION("Test proj antimeridian bbox")
{
    mapnik::projection prj_geog("+init=epsg:4326");
    mapnik::projection prj_proj("+init=epsg:2193");

    mapnik::proj_transform prj_trans_fwd(prj_proj, prj_geog);
    mapnik::proj_transform prj_trans_rev(prj_geog, prj_proj);

    // reference values taken from proj4 command line tool:
    // (non-corner points assume PROJ_ENVELOPE_POINTS == 20)
    //
    //  cs2cs -Ef %.10f +init=epsg:2193 +to +init=epsg:4326 <<END
    //        2105800 3087000 # left-most
    //        1495200 3087000 # bottom-most
    //        2105800 7173000 # right-most
    //        3327000 7173000 # top-most
    //  END
    //
    // wrong = mapnik.Box2d(-177.3145325044, -62.3337481525,
    //                       178.0277836332, -24.5845974912)
    const mapnik::box2d<double> better(-180.0, -62.3337481525,
                                        180.0, -24.5845974912);

    {
        mapnik::box2d<double> ext(274000, 3087000, 3327000, 7173000);
        prj_trans_fwd.forward(ext, PROJ_ENVELOPE_POINTS);
        CHECK(ext.minx() == Approx(better.minx()));
        CHECK(ext.miny() == Approx(better.miny()));
        CHECK(ext.maxx() == Approx(better.maxx()));
        CHECK(ext.maxy() == Approx(better.maxy()));
    }

    {
        // check the same logic works for .backward()
        mapnik::box2d<double> ext(274000, 3087000, 3327000, 7173000);
        prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS);
        CHECK(ext.minx() == Approx(better.minx()));
        CHECK(ext.miny() == Approx(better.miny()));
        CHECK(ext.maxx() == Approx(better.maxx()));
        CHECK(ext.maxy() == Approx(better.maxy()));
    }

    // reference values taken from proj4 command line tool:
    //
    //  cs2cs -Ef %.10f +init=epsg:2193 +to +init=epsg:4326 <<END
    //        274000 3087000 # left-most
    //        276000 3087000 # bottom-most
    //        276000 7173000 # right-most
    //        274000 7173000 # top-most
    //  END
    //
    const mapnik::box2d<double> normal(148.7667597489, -60.1222810241,
                                       159.9548489296, -24.9771195155);

    {
        // checks for not being snapped (ie. not antimeridian)
        mapnik::box2d<double> ext(274000, 3087000, 276000, 7173000);
        prj_trans_fwd.forward(ext, PROJ_ENVELOPE_POINTS);
        CHECK(ext.minx() == Approx(normal.minx()));
        CHECK(ext.miny() == Approx(normal.miny()));
        CHECK(ext.maxx() == Approx(normal.maxx()));
        CHECK(ext.maxy() == Approx(normal.maxy()));
    }

    {
        // check the same logic works for .backward()
        mapnik::box2d<double> ext(274000, 3087000, 276000, 7173000);
        prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS);
        CHECK(ext.minx() == Approx(normal.minx()));
        CHECK(ext.miny() == Approx(normal.miny()));
        CHECK(ext.maxx() == Approx(normal.maxx()));
        CHECK(ext.maxy() == Approx(normal.maxy()));
    }
}

}
<commit_msg>proj_transform: add test for strided coordinate array<commit_after>#include "catch.hpp"

#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/geometry/box2d.hpp>

#ifdef MAPNIK_USE_PROJ4
// proj4
#include <proj_api.h>
#endif

TEST_CASE("projection transform")
{

SECTION("Test bounding box transforms - 4326 to 3857")
{
    mapnik::projection proj_4326("+init=epsg:4326");
    mapnik::projection proj_3857("+init=epsg:3857");
    mapnik::proj_transform prj_trans(proj_4326, proj_3857);

    double minx = -45.0;
    double miny = 55.0;
    double maxx = -40.0;
    double maxy = 75.0;

    mapnik::box2d<double> bbox(minx, miny, maxx, maxy);

    prj_trans.forward(bbox);
    INFO(bbox.to_string());
    CHECK(bbox.minx() == Approx(-5009377.085697311));
    CHECK(bbox.miny() == Approx(7361866.1130511891));
    CHECK(bbox.maxx() == Approx(-4452779.631730943));
    CHECK(bbox.maxy() == Approx(12932243.1119920239));

    prj_trans.backward(bbox);
    CHECK(bbox.minx() == Approx(minx));
    CHECK(bbox.miny() == Approx(miny));
    CHECK(bbox.maxx() == Approx(maxx));
    CHECK(bbox.maxy() == Approx(maxy));

}

#if defined(MAPNIK_USE_PROJ4) && PJ_VERSION >= 480
SECTION("test pj_transform failure behavior")
{
    mapnik::projection proj_4269("+init=epsg:4269");
    mapnik::projection proj_3857("+init=epsg:3857");
    mapnik::proj_transform prj_trans(proj_4269, proj_3857);
    mapnik::proj_transform prj_trans2(proj_3857, proj_4269);

    auto proj_ctx0 = pj_ctx_alloc();
    REQUIRE( proj_ctx0 != nullptr );
    auto proj0 = pj_init_plus_ctx(proj_ctx0, proj_4269.params().c_str());
    REQUIRE( proj0 != nullptr );

    auto proj_ctx1 = pj_ctx_alloc();
    REQUIRE( proj_ctx1 != nullptr );
    auto proj1 = pj_init_plus_ctx(proj_ctx1, proj_3857.params().c_str());
    REQUIRE( proj1 != nullptr );

    // first test valid values directly against proj
    double x = -180.0;
    double y = -60.0;
    x *= DEG_TO_RAD;
    y *= DEG_TO_RAD;
    CHECK( x == Approx(-3.1415926536) );
    CHECK( y == Approx(-1.0471975512) );
    CHECK( 0 == pj_transform(proj0, proj1, 1, 0, &x, &y, nullptr) );
    CHECK( x == Approx(-20037508.3427892439) );
    CHECK( y == Approx(-8399737.8896366451) );

    // now test mapnik class
    double x0 = -180.0;
    double y0 = -60.0;
    CHECK( prj_trans.forward(&x0,&y0,nullptr,1,1) );
    CHECK( x0 == Approx(-20037508.3427892439) );
    CHECK( y0 == Approx(-8399737.8896366451) );
    double x1 = -180.0;
    double y1 = -60.0;
    CHECK( prj_trans2.backward(&x1,&y1,nullptr,1,1) );
    CHECK( x1 == Approx(-20037508.3427892439) );
    CHECK( y1 == Approx(-8399737.8896366451) );

    // longitude value outside the value range for mercator
    x = -181.0;
    y = -91.0;
    x *= DEG_TO_RAD;
    y *= DEG_TO_RAD;
    CHECK( x == Approx(-3.1590459461) );
    CHECK( y == Approx(-1.5882496193) );
    CHECK( 0 == pj_transform(proj0, proj1, 1, 0, &x, &y, nullptr) );
    CHECK( std::isinf(x) );
    CHECK( std::isinf(y) );

    // now test mapnik class
    double x2 = -181.0;
    double y2 = -91.0;
    CHECK( false == prj_trans.forward(&x2,&y2,nullptr,1,1) );
    CHECK( std::isinf(x2) );
    CHECK( std::isinf(y2) );
    double x3 = -181.0;
    double y3 = -91.0;
    CHECK( false == prj_trans2.backward(&x3,&y3,nullptr,1,1) );
    CHECK( std::isinf(x3) );
    CHECK( std::isinf(y3) );

    // cleanup
    pj_ctx_free(proj_ctx0);
    proj_ctx0 = nullptr;
    pj_free(proj0);
    proj0 = nullptr;
    pj_ctx_free(proj_ctx1);
    proj_ctx1 = nullptr;
    pj_free(proj1);
    proj1 = nullptr;
}

#endif

// Github Issue https://github.com/mapnik/mapnik/issues/2648
SECTION("Test proj antimeridian bbox")
{
    mapnik::projection prj_geog("+init=epsg:4326");
    mapnik::projection prj_proj("+init=epsg:2193");

    mapnik::proj_transform prj_trans_fwd(prj_proj, prj_geog);
    mapnik::proj_transform prj_trans_rev(prj_geog, prj_proj);

    // reference values taken from proj4 command line tool:
    // (non-corner points assume PROJ_ENVELOPE_POINTS == 20)
    //
    //  cs2cs -Ef %.10f +init=epsg:2193 +to +init=epsg:4326 <<END
    //        2105800 3087000 # left-most
    //        1495200 3087000 # bottom-most
    //        2105800 7173000 # right-most
    //        3327000 7173000 # top-most
    //  END
    //
    // wrong = mapnik.Box2d(-177.3145325044, -62.3337481525,
    //                       178.0277836332, -24.5845974912)
    const mapnik::box2d<double> better(-180.0, -62.3337481525,
                                        180.0, -24.5845974912);

    {
        mapnik::box2d<double> ext(274000, 3087000, 3327000, 7173000);
        prj_trans_fwd.forward(ext, PROJ_ENVELOPE_POINTS);
        CHECK(ext.minx() == Approx(better.minx()));
        CHECK(ext.miny() == Approx(better.miny()));
        CHECK(ext.maxx() == Approx(better.maxx()));
        CHECK(ext.maxy() == Approx(better.maxy()));
    }

    {
        // check the same logic works for .backward()
        mapnik::box2d<double> ext(274000, 3087000, 3327000, 7173000);
        prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS);
        CHECK(ext.minx() == Approx(better.minx()));
        CHECK(ext.miny() == Approx(better.miny()));
        CHECK(ext.maxx() == Approx(better.maxx()));
        CHECK(ext.maxy() == Approx(better.maxy()));
    }

    // reference values taken from proj4 command line tool:
    //
    //  cs2cs -Ef %.10f +init=epsg:2193 +to +init=epsg:4326 <<END
    //        274000 3087000 # left-most
    //        276000 3087000 # bottom-most
    //        276000 7173000 # right-most
    //        274000 7173000 # top-most
    //  END
    //
    const mapnik::box2d<double> normal(148.7667597489, -60.1222810241,
                                       159.9548489296, -24.9771195155);

    {
        // checks for not being snapped (ie. not antimeridian)
        mapnik::box2d<double> ext(274000, 3087000, 276000, 7173000);
        prj_trans_fwd.forward(ext, PROJ_ENVELOPE_POINTS);
        CHECK(ext.minx() == Approx(normal.minx()));
        CHECK(ext.miny() == Approx(normal.miny()));
        CHECK(ext.maxx() == Approx(normal.maxx()));
        CHECK(ext.maxy() == Approx(normal.maxy()));
    }

    {
        // check the same logic works for .backward()
        mapnik::box2d<double> ext(274000, 3087000, 276000, 7173000);
        prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS);
        CHECK(ext.minx() == Approx(normal.minx()));
        CHECK(ext.miny() == Approx(normal.miny()));
        CHECK(ext.maxx() == Approx(normal.maxx()));
        CHECK(ext.maxy() == Approx(normal.maxy()));
    }
}

SECTION("proj_transform of coordinate arrays with stride > 1")
{
    mapnik::projection const proj_4326("+init=epsg:4326");
    mapnik::projection const proj_3857("+init=epsg:3857");
    mapnik::projection const proj_2193("+init=epsg:2193");

    SECTION("lonlat <-> Web Mercator")
    {
        //  cs2cs -Ef %.10f +init=epsg:4326 +to +init=epsg:3857 <<END
        //      170.142139 -43.595056
        //      175.566667 -39.283333
        //  END
        //
        //  170.142139 -43.595056   18940136.2759583741 -5402988.5324898539
        //  175.566667 -39.283333   19543991.9707122259 -4762338.2380718365
        //
        mapnik::geometry::point<double> points[] = {{ 170.142139, -43.595056 },
                                                    { 175.566667, -39.283333 }};
        // this transform is calculated by Mapnik (well_known_srs.cpp)
        mapnik::proj_transform lonlat_to_webmerc(proj_4326, proj_3857);
        CHECKED_IF(lonlat_to_webmerc.forward(&points[0].x, &points[0].y, nullptr, 2, 2))
        {
            CHECK(points[0].x == Approx(18940136.2759583741));
            CHECK(points[0].y == Approx(-5402988.5324898539));
            CHECK(points[1].x == Approx(19543991.9707122259));
            CHECK(points[1].y == Approx(-4762338.2380718365));
        }
        CHECKED_IF(lonlat_to_webmerc.backward(&points[0].x, &points[0].y, nullptr, 2, 2))
        {
            CHECK(points[0].x == Approx(170.142139));
            CHECK(points[0].y == Approx(-43.595056));
            CHECK(points[1].x == Approx(175.566667));
            CHECK(points[1].y == Approx(-39.283333));
        }
    }

    #ifdef MAPNIK_USE_PROJ4
    SECTION("lonlat <-> New Zealand Transverse Mercator 2000")
    {
        //  cs2cs -Ef %.10f +init=epsg:4326 +to +init=epsg:2193 <<END
        //      170.142139 -43.595056
        //      175.566667 -39.283333
        //  END
        //
        //  170.142139 -43.595056   1369316.0970041484  5169132.9750701785
        //  175.566667 -39.283333   1821377.9170061364  5648640.2106032455
        //
        mapnik::geometry::point<double> points[] = {{ 170.142139, -43.595056 },
                                                    { 175.566667, -39.283333 }};
        // this transform is not calculated by Mapnik (needs Proj4)
        mapnik::proj_transform lonlat_to_nztm(proj_4326, proj_2193);
        CHECKED_IF(lonlat_to_nztm.forward(&points[0].x, &points[0].y, nullptr, 2, 2))
        {
            CHECK(points[0].x == Approx(1369316.0970041484));
            CHECK(points[0].y == Approx(5169132.9750701785));
            CHECK(points[1].x == Approx(1821377.9170061364));
            CHECK(points[1].y == Approx(5648640.2106032455));
        }
        CHECKED_IF(lonlat_to_nztm.backward(&points[0].x, &points[0].y, nullptr, 2, 2))
        {
            CHECK(points[0].x == Approx(170.142139));
            CHECK(points[0].y == Approx(-43.595056));
            CHECK(points[1].x == Approx(175.566667));
            CHECK(points[1].y == Approx(-39.283333));
        }
    }
    #endif // MAPNIK_USE_PROJ4
}

}
<|endoftext|>


<commit_before>#ifndef RADIUMENGINE_ASSIMP_WRAPPER_HPP
#define RADIUMENGINE_ASSIMP_WRAPPER_HPP

#include <assimp/vector3.h>
#include <assimp/quaternion.h>
#include <assimp/matrix4x4.h>
#include <assimp/color4.h>
#include <assimp/types.h>

#include <Core/Math/LinearAlgebra.hpp>

namespace Ra {
    namespace IO {

        inline Core::Vector3 assimpToCore( const aiVector3D& v ) {
            return Core::Vector3( v.x, v.y, v.z );
        }

        inline aiVector3D coreToAssimp( const Core::Vector3& v ) {
            return aiVector3D( v.x(), v.y(), v.z() );
        }

        inline Core::Quaternion assimpToCore( const aiQuaternion& q ) {
            return Core::Quaternion( q.w, q.x, q.y, q.z );
        }

        inline Core::Transform assimpToCore( const aiMatrix4x4& M ) {
            Core::Matrix4 m( Core::Matrix4::Identity() );
            for( uint i = 0; i < 4; ++i )
            {
                for( uint j = 0; j < 4; ++j )
                {
                    m( i, j ) = M[i][j];
                }
            }
            return Core::Transform( m );
        }

        inline Core::Transform assimpToCore( const aiVector3D&    T,
                                             const aiQuaternion& R,
                                             const aiVector3D&    S ) {
            Core::Vector3    t = assimpToCore( T );
            Core::Quaternion r = assimpToCore( R );
            Core::Vector3    s = assimpToCore( S );
            Core::Transform M;
            M.fromPositionOrientationScale( t, r, s );
            return M;
        }

        inline Core::Color assimpToCore( const aiColor4D& c ) {
            return Core::Color( c.r, c.g, c.b, c.a );
        }

        inline std::string assimpToCore( const aiString& string ) {
            std::string result ( string.C_Str() );
            return result.empty() ? "default" : result;
        }

        inline Core::VectorNi assimpToCore( uint* index, const uint size )
        {
            Core::VectorNi v( size );
            for( uint i = 0; i < size; ++i ) {
                v[i] = index[i];
            }

            return v;
        }

    } // namespace IO
} // namespace Ra

#endif // RADIUMENGINE_ASSIMP_WRAPPER_HPP
<commit_msg>Handle filenames with \ characters<commit_after>#ifndef RADIUMENGINE_ASSIMP_WRAPPER_HPP
#define RADIUMENGINE_ASSIMP_WRAPPER_HPP

#include <assimp/vector3.h>
#include <assimp/quaternion.h>
#include <assimp/matrix4x4.h>
#include <assimp/color4.h>
#include <assimp/types.h>

#include <Core/Math/LinearAlgebra.hpp>

namespace Ra {
    namespace IO {

        inline Core::Vector3 assimpToCore( const aiVector3D& v ) {
            return Core::Vector3( v.x, v.y, v.z );
        }

        inline aiVector3D coreToAssimp( const Core::Vector3& v ) {
            return aiVector3D( v.x(), v.y(), v.z() );
        }

        inline Core::Quaternion assimpToCore( const aiQuaternion& q ) {
            return Core::Quaternion( q.w, q.x, q.y, q.z );
        }

        inline Core::Transform assimpToCore( const aiMatrix4x4& M ) {
            Core::Matrix4 m( Core::Matrix4::Identity() );
            for( uint i = 0; i < 4; ++i )
            {
                for( uint j = 0; j < 4; ++j )
                {
                    m( i, j ) = M[i][j];
                }
            }
            return Core::Transform( m );
        }

        inline Core::Transform assimpToCore( const aiVector3D&    T,
                                             const aiQuaternion& R,
                                             const aiVector3D&    S ) {
            Core::Vector3    t = assimpToCore( T );
            Core::Quaternion r = assimpToCore( R );
            Core::Vector3    s = assimpToCore( S );
            Core::Transform M;
            M.fromPositionOrientationScale( t, r, s );
            return M;
        }

        inline Core::Color assimpToCore( const aiColor4D& c ) {
            return Core::Color( c.r, c.g, c.b, c.a );
        }

        inline std::string assimpToCore( const aiString& string ) {
            std::string result ( string.C_Str() );
            std::transform(result.begin(), result.end(), result.begin(),
                           [](char in){if(in == '\\') return '/'; return in;});
            return result.empty() ? "default" : result;
        }

        inline Core::VectorNi assimpToCore( uint* index, const uint size )
        {
            Core::VectorNi v( size );
            for( uint i = 0; i < size; ++i ) {
                v[i] = index[i];
            }

            return v;
        }

    } // namespace IO
} // namespace Ra

#endif // RADIUMENGINE_ASSIMP_WRAPPER_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: canvasfont.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_canvas.hxx"

#include <canvas/debug.hxx>

#include <rtl/math.hxx>
#include <basegfx/numeric/ftools.hxx>

#include <vcl/metric.hxx>

#include "canvasfont.hxx"
#include "textlayout.hxx"

using namespace ::com::sun::star;

namespace vclcanvas
{
    CanvasFont::CanvasFont( const rendering::FontRequest&                   rFontRequest,
                            const uno::Sequence< beans::PropertyValue >&    ,
                            const geometry::Matrix2D&                       rFontMatrix,
                            const DeviceRef&                                rDevice ) :
        CanvasFont_Base( m_aMutex ),
        maFont( Font( rFontRequest.FontDescription.FamilyName,
                      rFontRequest.FontDescription.StyleName,
                      Size( 0, ::basegfx::fround(rFontRequest.CellSize) ) ) ),
        maFontRequest( rFontRequest ),
        mpRefDevice( rDevice )
    {
        maFont->SetAlign( ALIGN_BASELINE );
        maFont->SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
        maFont->SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );

        // TODO(F2): improve panose->vclenum conversion
        maFont->SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
        maFont->SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );

        // adjust to stretched/shrinked font
        if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
        {
            OutputDevice* pOutDev( mpRefDevice->getOutDev() );

            if( pOutDev )
            {
                const bool bOldMapState( pOutDev->IsMapModeEnabled() );
                pOutDev->EnableMapMode(FALSE);

                const Size aSize = pOutDev->GetFontMetric( *maFont ).GetSize();

                const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
                double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);

                if( !::basegfx::fTools::equalZero( fDividend) )
                    fStretch /= fDividend;

                const long nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );

                maFont->SetWidth( nNewWidth );

                pOutDev->EnableMapMode(bOldMapState);
            }
        }
    }

    void SAL_CALL CanvasFont::disposing()
    {
        tools::LocalGuard aGuard;

        mpRefDevice.clear();
    }

    uno::Reference< rendering::XTextLayout > SAL_CALL  CanvasFont::createTextLayout( const rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        if( !mpRefDevice.is() )
            return uno::Reference< rendering::XTextLayout >(); // we're disposed

        return new TextLayout( aText,
                               nDirection,
                               nRandomSeed,
                               Reference( this ),
                               mpRefDevice );
    }

    rendering::FontRequest SAL_CALL  CanvasFont::getFontRequest(  ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        return maFontRequest;
    }

    rendering::FontMetrics SAL_CALL  CanvasFont::getFontMetrics(  ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        // TODO(F1)
        return rendering::FontMetrics();
    }

    uno::Sequence< double > SAL_CALL  CanvasFont::getAvailableSizes(  ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        // TODO(F1)
        return uno::Sequence< double >();
    }

    uno::Sequence< beans::PropertyValue > SAL_CALL  CanvasFont::getExtraFontProperties(  ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        // TODO(F1)
        return uno::Sequence< beans::PropertyValue >();
    }

#define IMPLEMENTATION_NAME "VCLCanvas::CanvasFont"
#define SERVICE_NAME "com.sun.star.rendering.CanvasFont"

    ::rtl::OUString SAL_CALL CanvasFont::getImplementationName() throw( uno::RuntimeException )
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
    }

    sal_Bool SAL_CALL CanvasFont::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
    {
        return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
    }

    uno::Sequence< ::rtl::OUString > SAL_CALL CanvasFont::getSupportedServiceNames()  throw( uno::RuntimeException )
    {
        uno::Sequence< ::rtl::OUString > aRet(1);
        aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );

        return aRet;
    }

    ::Font CanvasFont::getVCLFont() const
    {
        return *maFont;
    }
}
<commit_msg>INTEGRATION: CWS canvas05 (1.8.68); FILE MERGED 2008/04/21 07:28:37 thb 1.8.68.2: RESYNC: (1.8-1.9); FILE MERGED 2007/12/20 22:18:59 thb 1.8.68.1: #i81092# #i78888# #i78925# #i79258# #i79437# #i84784# Large canvas rework, completing various areas such as color spaces, bitmap data access, true sprite and non-sprite implementations, and upstreaming the canvas parts of rodos emf+ rendering<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: canvasfont.cxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_canvas.hxx"

#include <canvas/debug.hxx>

#include <rtl/math.hxx>
#include <basegfx/numeric/ftools.hxx>

#include <vcl/metric.hxx>

#include "canvasfont.hxx"
#include "textlayout.hxx"

using namespace ::com::sun::star;

namespace vclcanvas
{
    CanvasFont::CanvasFont( const rendering::FontRequest&                   rFontRequest,
                            const uno::Sequence< beans::PropertyValue >&    ,
                            const geometry::Matrix2D&                       rFontMatrix,
                            rendering::XGraphicDevice&                      rDevice,
                            const OutDevProviderSharedPtr&                  rOutDevProvider ) :
        CanvasFont_Base( m_aMutex ),
        maFont( Font( rFontRequest.FontDescription.FamilyName,
                      rFontRequest.FontDescription.StyleName,
                      Size( 0, ::basegfx::fround(rFontRequest.CellSize) ) ) ),
        maFontRequest( rFontRequest ),
        mpRefDevice( &rDevice ),
        mpOutDevProvider( rOutDevProvider )
    {
        maFont->SetAlign( ALIGN_BASELINE );
        maFont->SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
        maFont->SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );

        // TODO(F2): improve panose->vclenum conversion
        maFont->SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
        maFont->SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );

        // adjust to stretched/shrinked font
        if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
        {
            OutputDevice& rOutDev( rOutDevProvider->getOutDev() );

            const bool bOldMapState( rOutDev.IsMapModeEnabled() );
            rOutDev.EnableMapMode(FALSE);

            const Size aSize = rOutDev.GetFontMetric( *maFont ).GetSize();

            const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
            double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);

            if( !::basegfx::fTools::equalZero( fDividend) )
                fStretch /= fDividend;

            const long nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );

            maFont->SetWidth( nNewWidth );

            rOutDev.EnableMapMode(bOldMapState);
        }
    }

    void SAL_CALL CanvasFont::disposing()
    {
        tools::LocalGuard aGuard;

        mpOutDevProvider.reset();
        mpRefDevice.clear();
    }

    uno::Reference< rendering::XTextLayout > SAL_CALL  CanvasFont::createTextLayout( const rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        if( !mpRefDevice.is() )
            return uno::Reference< rendering::XTextLayout >(); // we're disposed

        return new TextLayout( aText,
                               nDirection,
                               nRandomSeed,
                               Reference( this ),
                               mpRefDevice,
                               mpOutDevProvider);
    }

    rendering::FontRequest SAL_CALL  CanvasFont::getFontRequest(  ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        return maFontRequest;
    }

    rendering::FontMetrics SAL_CALL  CanvasFont::getFontMetrics(  ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        // TODO(F1)
        return rendering::FontMetrics();
    }

    uno::Sequence< double > SAL_CALL  CanvasFont::getAvailableSizes(  ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        // TODO(F1)
        return uno::Sequence< double >();
    }

    uno::Sequence< beans::PropertyValue > SAL_CALL  CanvasFont::getExtraFontProperties(  ) throw (uno::RuntimeException)
    {
        tools::LocalGuard aGuard;

        // TODO(F1)
        return uno::Sequence< beans::PropertyValue >();
    }

#define IMPLEMENTATION_NAME "VCLCanvas::CanvasFont"
#define SERVICE_NAME "com.sun.star.rendering.CanvasFont"

    ::rtl::OUString SAL_CALL CanvasFont::getImplementationName() throw( uno::RuntimeException )
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
    }

    sal_Bool SAL_CALL CanvasFont::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
    {
        return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
    }

    uno::Sequence< ::rtl::OUString > SAL_CALL CanvasFont::getSupportedServiceNames()  throw( uno::RuntimeException )
    {
        uno::Sequence< ::rtl::OUString > aRet(1);
        aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );

        return aRet;
    }

    ::Font CanvasFont::getVCLFont() const
    {
        return *maFont;
    }
}
<|endoftext|>


<commit_before>/*
	Copyright (c) 2003 - 2005, Arvid Norberg, Daniel Wallin
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions
	are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of Rasterbar Software nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <cassert>
#include <iostream>
#include <vector>
#include <utility>
#include <set>

#include "libtorrent/buffer.hpp"
#include "libtorrent/chained_buffer.hpp"
#include "libtorrent/socket.hpp"

#include "test.hpp"

using namespace libtorrent;

/*
template<class T>
T const& min_(T const& x, T const& y)
{
	return x < y ? x : y;
}

void test_speed()
{
	buffer b;

	char data[32];

	srand(0);

	boost::timer t;

	int const iterations = 5000000;
	int const step = iterations / 20;

	for (int i = 0; i < iterations; ++i)
	{
		int x = rand();

		if (i % step == 0) std::cerr << ".";

		std::size_t n = rand() % 32;
		n = 32;

		if (x % 2)
		{
			b.insert(data, data + n);
		}
		else
		{
			b.erase(min_(b.size(), n));
		}
	}

	float t1 = t.elapsed();
	std::cerr << "buffer elapsed: " << t.elapsed() << "\n";

	std::vector<char> v;

	srand(0);
	t.restart();

	for (int i = 0; i < iterations; ++i)
	{
		int x = rand();

		if (i % step == 0) std::cerr << ".";

		std::size_t n = rand() % 32;
		n = 32;

		if (x % 2)
		{
			v.insert(v.end(), data, data + n);
		}
		else
		{
			v.erase(v.begin(), v.begin() + min_(v.size(), n));
		}
	}

	float t2 = t.elapsed();
	std::cerr << "std::vector elapsed: " << t.elapsed() << "\n";

	assert(t1 < t2);
}
*/

// -- test buffer --

void test_buffer()
{
	char data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

	buffer b;

	TEST_CHECK(b.size() == 0);
	TEST_CHECK(b.capacity() == 0);
	TEST_CHECK(b.empty());

	b.resize(10);
	TEST_CHECK(b.size() == 10);
	TEST_CHECK(b.capacity() == 10);

	std::memcpy(b.begin(), data, 10);
	b.reserve(50);
	TEST_CHECK(std::memcmp(b.begin(), data, 10) == 0);
	TEST_CHECK(b.capacity() == 50);

	b.erase(b.begin() + 6, b.end());
	TEST_CHECK(std::memcmp(b.begin(), data, 6) == 0);
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 6);

	b.insert(b.begin(), data + 5, data + 10);
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 11);
	TEST_CHECK(std::memcmp(b.begin(), data + 5, 5) == 0);

	b.clear();
	TEST_CHECK(b.size() == 0);
	TEST_CHECK(b.capacity() == 50);

	b.insert(b.end(), data, data + 10);
	TEST_CHECK(b.size() == 10);
	TEST_CHECK(std::memcmp(b.begin(), data, 10) == 0);

	b.erase(b.begin(), b.end());
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 0);

	buffer().swap(b);
	TEST_CHECK(b.capacity() == 0);

}

// -- test chained buffer --

std::set<char*> buffer_list;

void free_buffer(char* m)
{
	std::set<char*>::iterator i = buffer_list.find(m);
	TEST_CHECK(i != buffer_list.end());

	buffer_list.erase(i);
	std::free(m);
}

char* allocate_buffer(int size)
{
	char* mem = (char*)std::malloc(size);
	buffer_list.insert(mem);
	return mem;
}

template <class T>
int copy_buffers(T const& b, char* target)
{
	int copied = 0;
	for (typename T::const_iterator i = b.begin()
		, end(b.end()); i != end; ++i)
	{
		memcpy(target, libtorrent::asio::buffer_cast<char const*>(*i), libtorrent::asio::buffer_size(*i));
		target += libtorrent::asio::buffer_size(*i);
		copied += libtorrent::asio::buffer_size(*i);
	}
	return copied;
}

bool compare_chained_buffer(chained_buffer& b, char const* mem, int size)
{
	if (size == 0) return true;
	std::vector<char> flat(size);
	std::list<libtorrent::asio::const_buffer> const& iovec2 = b.build_iovec(size);
	int copied = copy_buffers(iovec2, &flat[0]);
	TEST_CHECK(copied == size);
	return std::memcmp(&flat[0], mem, size) == 0;
}

void test_chained_buffer()
{
	char data[] = "foobar";
	{
		chained_buffer b;

		TEST_CHECK(b.empty());
		TEST_CHECK(b.capacity() == 0);
		TEST_CHECK(b.size() == 0);
		TEST_CHECK(b.space_in_last_buffer() == 0);
		TEST_CHECK(buffer_list.empty());

		char* b1 = allocate_buffer(512);
		std::memcpy(b1, data, 6);
		b.append_buffer(b1, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 1);

		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 6);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		b.pop_front(3);

		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 3);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		bool ret = b.append(data, 6);

		TEST_CHECK(ret == true);
		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 9);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 12);

		char data2[1024];
		ret = b.append(data2, 1024);

		TEST_CHECK(ret == false);

		char* b2 = allocate_buffer(512);
		std::memcpy(b2, data, 6);
		b.append_buffer(b2, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 2);

		char* b3 = allocate_buffer(512);
		std::memcpy(b3, data, 6);
		b.append_buffer(b3, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 3);

		TEST_CHECK(b.capacity() == 512 * 3);
		TEST_CHECK(b.size() == 21);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		TEST_CHECK(compare_chained_buffer(b, "barfoobar", 9));

		for (int i = 1; i < 21; ++i)
			TEST_CHECK(compare_chained_buffer(b, "barfoobarfoobarfoobar", i));

		b.pop_front(5 + 6);

		TEST_CHECK(buffer_list.size() == 2);
		TEST_CHECK(b.capacity() == 512 * 2);
		TEST_CHECK(b.size() == 10);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		char const* str = "obarfooba";
		TEST_CHECK(compare_chained_buffer(b, str, 9));

		for (int i = 0; i < 9; ++i)
		{
			b.pop_front(1);
			++str;
			TEST_CHECK(compare_chained_buffer(b, str, 8 - i));
			TEST_CHECK(b.size() == 9 - i);
		}

		char* b4 = allocate_buffer(20);
		std::memcpy(b4, data, 6);
		std::memcpy(b4 + 6, data, 6);
		b.append_buffer(b4, 20, 12, (void(*)(char*))&free_buffer);
		TEST_CHECK(b.space_in_last_buffer() == 8);

		ret = b.append(data, 6);
		TEST_CHECK(ret == true);
		TEST_CHECK(b.space_in_last_buffer() == 2);
		std::cout << b.space_in_last_buffer() << std::endl;
		ret = b.append(data, 2);
		TEST_CHECK(ret == true);
		TEST_CHECK(b.space_in_last_buffer() == 0);
		std::cout << b.space_in_last_buffer() << std::endl;

		char* b5 = allocate_buffer(20);
		std::memcpy(b4, data, 6);
		b.append_buffer(b5, 20, 6, (void(*)(char*))&free_buffer);

		b.pop_front(22);
		TEST_CHECK(b.size() == 5);
	}
	TEST_CHECK(buffer_list.empty());
}

int test_main()
{
	test_buffer();
	test_chained_buffer();
	return 0;
}

<commit_msg>tweak chained buffer test<commit_after>/*
	Copyright (c) 2003 - 2005, Arvid Norberg, Daniel Wallin
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions
	are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of Rasterbar Software nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <cassert>
#include <iostream>
#include <vector>
#include <utility>
#include <set>

#include "libtorrent/buffer.hpp"
#include "libtorrent/chained_buffer.hpp"
#include "libtorrent/socket.hpp"

#include "test.hpp"

using namespace libtorrent;

/*
template<class T>
T const& min_(T const& x, T const& y)
{
	return x < y ? x : y;
}

void test_speed()
{
	buffer b;

	char data[32];

	srand(0);

	boost::timer t;

	int const iterations = 5000000;
	int const step = iterations / 20;

	for (int i = 0; i < iterations; ++i)
	{
		int x = rand();

		if (i % step == 0) std::cerr << ".";

		std::size_t n = rand() % 32;
		n = 32;

		if (x % 2)
		{
			b.insert(data, data + n);
		}
		else
		{
			b.erase(min_(b.size(), n));
		}
	}

	float t1 = t.elapsed();
	std::cerr << "buffer elapsed: " << t.elapsed() << "\n";

	std::vector<char> v;

	srand(0);
	t.restart();

	for (int i = 0; i < iterations; ++i)
	{
		int x = rand();

		if (i % step == 0) std::cerr << ".";

		std::size_t n = rand() % 32;
		n = 32;

		if (x % 2)
		{
			v.insert(v.end(), data, data + n);
		}
		else
		{
			v.erase(v.begin(), v.begin() + min_(v.size(), n));
		}
	}

	float t2 = t.elapsed();
	std::cerr << "std::vector elapsed: " << t.elapsed() << "\n";

	assert(t1 < t2);
}
*/

// -- test buffer --

void test_buffer()
{
	char data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

	buffer b;

	TEST_CHECK(b.size() == 0);
	TEST_CHECK(b.capacity() == 0);
	TEST_CHECK(b.empty());

	b.resize(10);
	TEST_CHECK(b.size() == 10);
	TEST_CHECK(b.capacity() == 10);

	std::memcpy(b.begin(), data, 10);
	b.reserve(50);
	TEST_CHECK(std::memcmp(b.begin(), data, 10) == 0);
	TEST_CHECK(b.capacity() == 50);

	b.erase(b.begin() + 6, b.end());
	TEST_CHECK(std::memcmp(b.begin(), data, 6) == 0);
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 6);

	b.insert(b.begin(), data + 5, data + 10);
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 11);
	TEST_CHECK(std::memcmp(b.begin(), data + 5, 5) == 0);

	b.clear();
	TEST_CHECK(b.size() == 0);
	TEST_CHECK(b.capacity() == 50);

	b.insert(b.end(), data, data + 10);
	TEST_CHECK(b.size() == 10);
	TEST_CHECK(std::memcmp(b.begin(), data, 10) == 0);

	b.erase(b.begin(), b.end());
	TEST_CHECK(b.capacity() == 50);
	TEST_CHECK(b.size() == 0);

	buffer().swap(b);
	TEST_CHECK(b.capacity() == 0);

}

// -- test chained buffer --

std::set<char*> buffer_list;

void free_buffer(char* m)
{
	std::set<char*>::iterator i = buffer_list.find(m);
	TEST_CHECK(i != buffer_list.end());

	buffer_list.erase(i);
	std::free(m);
}

char* allocate_buffer(int size)
{
	char* mem = (char*)std::malloc(size);
	buffer_list.insert(mem);
	return mem;
}

template <class T>
int copy_buffers(T const& b, char* target)
{
	int copied = 0;
	for (typename T::const_iterator i = b.begin()
		, end(b.end()); i != end; ++i)
	{
		memcpy(target, libtorrent::asio::buffer_cast<char const*>(*i), libtorrent::asio::buffer_size(*i));
		target += libtorrent::asio::buffer_size(*i);
		copied += libtorrent::asio::buffer_size(*i);
	}
	return copied;
}

bool compare_chained_buffer(chained_buffer& b, char const* mem, int size)
{
	if (size == 0) return true;
	std::vector<char> flat(size);
	std::list<libtorrent::asio::const_buffer> const& iovec2 = b.build_iovec(size);
	int copied = copy_buffers(iovec2, &flat[0]);
	TEST_CHECK(copied == size);
	return std::memcmp(&flat[0], mem, size) == 0;
}

void test_chained_buffer()
{
	char data[] = "foobar";
	{
		chained_buffer b;

		TEST_CHECK(b.empty());
		TEST_EQUAL(b.capacity(), 0);
		TEST_EQUAL(b.size(), 0);
		TEST_EQUAL(b.space_in_last_buffer(), 0);
		TEST_CHECK(buffer_list.empty());

		// there are no buffers, we should not be able to allocate
		// an appendix in an existing buffer
		TEST_EQUAL(b.allocate_appendix(1), 0);

		char* b1 = allocate_buffer(512);
		std::memcpy(b1, data, 6);
		b.append_buffer(b1, 512, 6, (void(*)(char*))&free_buffer);
		TEST_EQUAL(buffer_list.size(), 1);

		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 6);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		b.pop_front(3);

		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 3);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		bool ret = b.append(data, 6);

		TEST_CHECK(ret == true);
		TEST_CHECK(b.capacity() == 512);
		TEST_CHECK(b.size() == 9);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 12);

		char data2[1024];
		ret = b.append(data2, 1024);

		TEST_CHECK(ret == false);

		char* b2 = allocate_buffer(512);
		std::memcpy(b2, data, 6);
		b.append_buffer(b2, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 2);

		char* b3 = allocate_buffer(512);
		std::memcpy(b3, data, 6);
		b.append_buffer(b3, 512, 6, (void(*)(char*))&free_buffer);
		TEST_CHECK(buffer_list.size() == 3);

		TEST_CHECK(b.capacity() == 512 * 3);
		TEST_CHECK(b.size() == 21);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		TEST_CHECK(compare_chained_buffer(b, "barfoobar", 9));

		for (int i = 1; i < 21; ++i)
			TEST_CHECK(compare_chained_buffer(b, "barfoobarfoobarfoobar", i));

		b.pop_front(5 + 6);

		TEST_CHECK(buffer_list.size() == 2);
		TEST_CHECK(b.capacity() == 512 * 2);
		TEST_CHECK(b.size() == 10);
		TEST_CHECK(!b.empty());
		TEST_CHECK(b.space_in_last_buffer() == 512 - 6);

		char const* str = "obarfooba";
		TEST_CHECK(compare_chained_buffer(b, str, 9));

		for (int i = 0; i < 9; ++i)
		{
			b.pop_front(1);
			++str;
			TEST_CHECK(compare_chained_buffer(b, str, 8 - i));
			TEST_CHECK(b.size() == 9 - i);
		}

		char* b4 = allocate_buffer(20);
		std::memcpy(b4, data, 6);
		std::memcpy(b4 + 6, data, 6);
		b.append_buffer(b4, 20, 12, (void(*)(char*))&free_buffer);
		TEST_CHECK(b.space_in_last_buffer() == 8);

		ret = b.append(data, 6);
		TEST_CHECK(ret == true);
		TEST_CHECK(b.space_in_last_buffer() == 2);
		std::cout << b.space_in_last_buffer() << std::endl;
		ret = b.append(data, 2);
		TEST_CHECK(ret == true);
		TEST_CHECK(b.space_in_last_buffer() == 0);
		std::cout << b.space_in_last_buffer() << std::endl;

		char* b5 = allocate_buffer(20);
		std::memcpy(b4, data, 6);
		b.append_buffer(b5, 20, 6, (void(*)(char*))&free_buffer);

		b.pop_front(22);
		TEST_CHECK(b.size() == 5);
	}
	TEST_CHECK(buffer_list.empty());
}

int test_main()
{
	test_buffer();
	test_chained_buffer();
	return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, The Regents of the University of California (Regents).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *    3. Neither the name of the copyright holder nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Please contact the author(s) of this library if you have any questions.
 * Authors: David Fridovich-Keil   ( dfk@eecs.berkeley.edu )
 *          Erik Nelson            ( eanelson@eecs.berkeley.edu )
 */

#include <Eigen/Dense>
#include <camera/camera.h>
#include <math.h>

#include <gflags/gflags.h>
#include <gtest/gtest.h>

namespace bsfm {

TEST(Camera, TestCameraExtrinsics) {
  // Make sure that default constructor makes the extrinsics matrix identity.
  CameraExtrinsics extrinsics;

  double wx = 5.1283, wy = -1282.123, wz = 8713.1237;
  double cx = 0.0, cy = 0.0, cz = 0.0;
  extrinsics.WorldToCamera(wx, wy, wz, &cx, &cy, &cz);
  EXPECT_EQ(wx, cx);
  EXPECT_EQ(wy, cy);
  EXPECT_EQ(wz, cz);

  cx = 2397.123897, cy = -1283.127836, cz = -8129.12387;
  extrinsics.CameraToWorld(cx, cy, cz, &wx, &wy, &wz);
  EXPECT_EQ(cx, wx);
  EXPECT_EQ(cy, wy);
  EXPECT_EQ(cz, wz);

  // Make sure points are translated correctly.
  Eigen::Matrix4d w2b = Eigen::Matrix4d::Identity();
  w2b(0, 3) = 5.0;
  w2b(1, 3) = 8.0;
  w2b(2, 3) = -10.0;

  Eigen::Matrix4d b2c = Eigen::Matrix4d::Identity();
  b2c(0, 3) = -3.0;
  b2c(1, 3) = -10.0;
  b2c(2, 3) = 4.0;

  extrinsics.SetWorldToBody(w2b);
  extrinsics.SetBodyToCamera(b2c);

  cx = 0.0, cy = 0.0, cz = 0.0;
  extrinsics.WorldToCamera(wx, wy, wz, &cx, &cy, &cz);
  EXPECT_EQ(wx + 2.0, cx);
  EXPECT_EQ(wy - 2.0, cy);
  EXPECT_EQ(wz - 6.0, cz);

  wx = 0.0, wy = 0.0, wz = 0.0;
  extrinsics.CameraToWorld(cx, cy, cz, &wx, &wy, &wz);
  EXPECT_EQ(cx - 2.0, wx);
  EXPECT_EQ(cy + 2.0, wy);
  EXPECT_EQ(cz + 6.0, wz);

  Eigen::Matrix<double, 3, 4> expected_extrinsic_matrix;
  expected_extrinsic_matrix.Zero();
  expected_extrinsic_matrix(1, 1) = 1.0;
  expected_extrinsic_matrix(2, 2) = 1.0;
  expected_extrinsic_matrix(3, 3) = 1.0;
  expected_extrinsic_matrix(0, 3) = 2.0;
  expected_extrinsic_matrix(1, 3) = -2.0;
  expected_extrinsic_matrix(2, 3) = -6.0;
  EXPECT_TRUE(expected_extrinsic_matrix == extrinsics.ExtrinsicsMatrix());
}

TEST(Camera, TestCameraIntrinsics) {
  const int kImageWidth = 1920;
  const int kImageHeight = 1080;
  const double kVerticalFov = 90.0 * M_PI / 180.0;

  CameraIntrinsics intrinsics;
  intrinsics.SetImageLeft(0);
  intrinsics.SetImageTop(0);
  intrinsics.SetImageWidth(kImageWidth);
  intrinsics.SetImageHeight(kImageHeight);
  // Setting vertical fov also sets f_v().
  intrinsics.SetVerticalFOV(kVerticalFov);
  // Setting f_u also sets horizontal fov.
  intrinsics.SetFU(intrinsics.f_v());
  intrinsics.SetCU(0.5 * kImageWidth);
  intrinsics.SetCV(0.5 * kImageHeight);

  // No radial distortion.
  intrinsics.SetK(0.0, 0.0, 0.0, 0.0, 0.0);

  Eigen::Matrix3d expected_intrinsic_matrix = Eigen::Matrix3d::Identity();
  expected_intrinsic_matrix(0, 0) = intrinsics.f_u();
  expected_intrinsic_matrix(1, 1) = intrinsics.f_v();
  expected_intrinsic_matrix(0, 2) = intrinsics.c_u();
  expected_intrinsic_matrix(1, 2) = intrinsics.c_v();

  EXPECT_TRUE(expected_intrinsic_matrix.isApprox(intrinsics.IntrinsicsMatrix()));

  // Camera to image on point behind the camera.
  double cx = 0.0, cy = 1.5, cz = -1.0;
  EXPECT_TRUE(!intrinsics.CameraToImage(cx, cy, cz, nullptr, nullptr));
  double u = 0.0, v = 0.0;
  EXPECT_TRUE(!intrinsics.CameraToImage(cx, cy, cz, &u, &v));

  // Camera to image on point in front of camera.
  cz = 3.0;
  EXPECT_TRUE(intrinsics.CameraToImage(cx, cy, cz, &u, &v));
  EXPECT_FLOAT_EQ(0.25 * kImageHeight, v);
  EXPECT_FLOAT_EQ(0.5 * kImageWidth, u);

  cx = -3.0;
  double expected_u = kImageWidth / 2.0 - intrinsics.f_u();
  EXPECT_TRUE(intrinsics.CameraToImage(cx, cy, cz, &u, &v));
  EXPECT_FLOAT_EQ(0.25 * kImageHeight, v);
  EXPECT_FLOAT_EQ(expected_u, u);
}

TEST(Camera, TestCamera) {
  const int kImageWidth = 1920;
  const int kImageHeight = 1080;
  const double kVerticalFov = 90.0 * M_PI / 180.0;

  CameraIntrinsics intrinsics;
  intrinsics.SetImageLeft(0);
  intrinsics.SetImageTop(0);
  intrinsics.SetImageWidth(kImageWidth);
  intrinsics.SetImageHeight(kImageHeight);
  // Setting vertical fov also sets f_v().
  intrinsics.SetVerticalFOV(kVerticalFov);
  // Setting f_u also sets horizontal fov.
  intrinsics.SetFU(intrinsics.f_v());
  intrinsics.SetCU(0.5 * kImageWidth);
  intrinsics.SetCV(0.5 * kImageHeight);

  // No radial distortion.
  intrinsics.SetK(0.0, 0.0, 0.0, 0.0, 0.0);

  CameraExtrinsics extrinsics;

  // Pure translation.
  Eigen::Matrix4d w2c = Eigen::Matrix4d::Identity();
  w2c(0, 3) = 4.0;
  w2c(1, 3) = 2.0;
  w2c(2, 3) = -0.0;

  // Make some points and project them into a second camera.
  Camera camera1, camera2;
  Eigen::Matrix4d eye = Eigen::Matrix4d::Identity();
  camera1.SetIntrinsics(intrinsics);
  camera1.SetExtrinsics(Pose(eye));
  camera2.SetIntrinsics(intrinsics);
  camera2.SetExtrinsics(extrinsics);

  // TODO (eanelson): Write test case.

}

}  //\namespace bsfm
<commit_msg>camera extrinsics test passes<commit_after>/*
 * Copyright (c) 2015, The Regents of the University of California (Regents).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *    3. Neither the name of the copyright holder nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Please contact the author(s) of this library if you have any questions.
 * Authors: David Fridovich-Keil   ( dfk@eecs.berkeley.edu )
 *          Erik Nelson            ( eanelson@eecs.berkeley.edu )
 */

#include <Eigen/Dense>
#include <camera/camera.h>
#include <math.h>

#include <gflags/gflags.h>
#include <gtest/gtest.h>

namespace bsfm {

TEST(Camera, TestCameraExtrinsics) {
  // Make sure that default constructor makes the extrinsics matrix identity.
  CameraExtrinsics extrinsics;

  double wx = 5.1283, wy = -1282.123, wz = 8713.1237;
  double cx = 0.0, cy = 0.0, cz = 0.0;
  extrinsics.WorldToCamera(wx, wy, wz, &cx, &cy, &cz);
  EXPECT_EQ(wx, cx);
  EXPECT_EQ(wy, cy);
  EXPECT_EQ(wz, cz);

  cx = 2397.123897, cy = -1283.127836, cz = -8129.12387;
  extrinsics.CameraToWorld(cx, cy, cz, &wx, &wy, &wz);
  EXPECT_EQ(cx, wx);
  EXPECT_EQ(cy, wy);
  EXPECT_EQ(cz, wz);

  // Make sure points are translated correctly.
  Eigen::Matrix4d w2b = Eigen::Matrix4d::Identity();
  w2b(0, 3) = 5.0;
  w2b(1, 3) = 8.0;
  w2b(2, 3) = -10.0;

  Eigen::Matrix4d b2c = Eigen::Matrix4d::Identity();
  b2c(0, 3) = -3.0;
  b2c(1, 3) = -10.0;
  b2c(2, 3) = 4.0;

  extrinsics.SetWorldToBody(w2b);
  extrinsics.SetBodyToCamera(b2c);

  cx = 0.0, cy = 0.0, cz = 0.0;
  extrinsics.WorldToCamera(wx, wy, wz, &cx, &cy, &cz);
  EXPECT_EQ(wx + 2.0, cx);
  EXPECT_EQ(wy - 2.0, cy);
  EXPECT_EQ(wz - 6.0, cz);

  wx = 0.0, wy = 0.0, wz = 0.0;
  extrinsics.CameraToWorld(cx, cy, cz, &wx, &wy, &wz);
  EXPECT_EQ(cx - 2.0, wx);
  EXPECT_EQ(cy + 2.0, wy);
  EXPECT_EQ(cz + 6.0, wz);

  Eigen::Matrix<double, 3, 4> expected_extrinsic_matrix;
  expected_extrinsic_matrix.Zero();
  expected_extrinsic_matrix(0, 0) = 1.0;
  expected_extrinsic_matrix(1, 1) = 1.0;
  expected_extrinsic_matrix(2, 2) = 1.0;
  expected_extrinsic_matrix(0, 3) = 2.0;
  expected_extrinsic_matrix(1, 3) = -2.0;
  expected_extrinsic_matrix(2, 3) = -6.0;

  EXPECT_TRUE(expected_extrinsic_matrix.isApprox(extrinsics.ExtrinsicsMatrix()));
}

TEST(Camera, TestCameraIntrinsics) {
  const int kImageWidth = 1920;
  const int kImageHeight = 1080;
  const double kVerticalFov = 90.0 * M_PI / 180.0;

  CameraIntrinsics intrinsics;
  intrinsics.SetImageLeft(0);
  intrinsics.SetImageTop(0);
  intrinsics.SetImageWidth(kImageWidth);
  intrinsics.SetImageHeight(kImageHeight);
  // Setting vertical fov also sets f_v().
  intrinsics.SetVerticalFOV(kVerticalFov);
  // Setting f_u also sets horizontal fov.
  intrinsics.SetFU(intrinsics.f_v());
  intrinsics.SetCU(0.5 * kImageWidth);
  intrinsics.SetCV(0.5 * kImageHeight);

  // No radial distortion.
  intrinsics.SetK(0.0, 0.0, 0.0, 0.0, 0.0);

  Eigen::Matrix3d expected_intrinsic_matrix = Eigen::Matrix3d::Identity();
  expected_intrinsic_matrix(0, 0) = intrinsics.f_u();
  expected_intrinsic_matrix(1, 1) = intrinsics.f_v();
  expected_intrinsic_matrix(0, 2) = intrinsics.c_u();
  expected_intrinsic_matrix(1, 2) = intrinsics.c_v();

  EXPECT_TRUE(expected_intrinsic_matrix.isApprox(intrinsics.IntrinsicsMatrix()));

  // Camera to image on point behind the camera.
  double cx = 0.0, cy = 1.5, cz = -1.0;
  EXPECT_TRUE(!intrinsics.CameraToImage(cx, cy, cz, nullptr, nullptr));
  double u = 0.0, v = 0.0;
  EXPECT_TRUE(!intrinsics.CameraToImage(cx, cy, cz, &u, &v));

  // Camera to image on point in front of camera.
  cz = 3.0;
  EXPECT_TRUE(intrinsics.CameraToImage(cx, cy, cz, &u, &v));
  EXPECT_FLOAT_EQ(0.25 * kImageHeight, v);
  EXPECT_FLOAT_EQ(0.5 * kImageWidth, u);

  cx = -3.0;
  double expected_u = kImageWidth / 2.0 - intrinsics.f_u();
  EXPECT_TRUE(intrinsics.CameraToImage(cx, cy, cz, &u, &v));
  EXPECT_FLOAT_EQ(0.25 * kImageHeight, v);
  EXPECT_FLOAT_EQ(expected_u, u);
}

TEST(Camera, TestCamera) {
  const int kImageWidth = 1920;
  const int kImageHeight = 1080;
  const double kVerticalFov = 90.0 * M_PI / 180.0;

  CameraIntrinsics intrinsics;
  intrinsics.SetImageLeft(0);
  intrinsics.SetImageTop(0);
  intrinsics.SetImageWidth(kImageWidth);
  intrinsics.SetImageHeight(kImageHeight);
  // Setting vertical fov also sets f_v().
  intrinsics.SetVerticalFOV(kVerticalFov);
  // Setting f_u also sets horizontal fov.
  intrinsics.SetFU(intrinsics.f_v());
  intrinsics.SetCU(0.5 * kImageWidth);
  intrinsics.SetCV(0.5 * kImageHeight);

  // No radial distortion.
  intrinsics.SetK(0.0, 0.0, 0.0, 0.0, 0.0);

  CameraExtrinsics extrinsics;

  // Pure translation.
  Eigen::Matrix4d w2c = Eigen::Matrix4d::Identity();
  w2c(0, 3) = 4.0;
  w2c(1, 3) = 2.0;
  w2c(2, 3) = -0.0;

  // Make some points and project them into a second camera.
  Camera camera1, camera2;
  Eigen::Matrix4d eye = Eigen::Matrix4d::Identity();
  camera1.SetIntrinsics(intrinsics);
  camera1.SetExtrinsics(Pose(eye));
  camera2.SetIntrinsics(intrinsics);
  camera2.SetExtrinsics(extrinsics);

  // TODO (eanelson): Write test case.

}

}  //\namespace bsfm
<|endoftext|>


<commit_before>#ifndef ecmdClientCapi_H
#define ecmdClientCapi_H

/* $Header$ */

/**
 * @file ecmdClientCapi.H
 * @brief eCMD C/C++ Client Interface
*/

//--------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------
#include <ecmdReturnCodes.H>
#include <ecmdStructs.H>
#include <ecmdDataBuffer.H>

//--------------------------------------------------------------------
//  Forward References
//--------------------------------------------------------------------

/* Functions in here are defined as extern C for the following reasons:
 1)  Keeps Function names small by preventing C++ "mangling"
 2)  Allows (C-based) perl interpreter to access these functions

*/
extern "C" {

/** @name Load/Unload Functions */
//@{
/**
 @brief Load the eCMD DLL
 @retval ECMD_SUCCESS if successful load
 @retval ECMD_INVALID_DLL_VERSION if Dll version loaded doesn't match client version
 @retval nonzero if unsuccessful
 @post eCMD DLL is loaded into memory and initialized
 @see unloadDll

       - This function loads the DLL based on ???.
       - Name limit of 255 characters.
       - Errors in loading are printed to STDOUT.
*/
int ecmdLoadDll();

/**
 @brief Unload the eCMD DLL
 @retval ECMD_SUCCESS if successful load
 @retval nonzero if unsuccessful
 @see loadDll

 - Errors in unloading are printed to STDOUT.
*/

int ecmdUnloadDll();

/**
 @brief Initialize the eCMD DLL
 @retval ECMD_SUCCESS if successful load  nonzero if unsuccessful
 @param argc Passed from Command line Arguments
 @param argv Passed from Command line Arguments
 @pre loadDll must have been called
 @post Global options (ex. -debug, -p#, -c#) will be removed from arg list
 @see loadDll

 - initializes objects in the DLL.
 - argc/argv get passed to the eCMD DLL.
 - Global options such as -debug flags and -p#, -c# will be parsed out.
 - Position flags can be queried later with functions like wasposselected()
*/

int ecmdInitDll(int argc, char* argv[]);

//@}

/** @name Query Functions */
//@{
/**
 @brief Query configuration information from the DLL
 @param target Struct that contains partial information to limit query results
 @param queryData Return vector from query - in numerical order by cageId
 @retval ECMD_SUCCESS if successful
 @retval nonzero on failure

 The target paramater should be filled in with as much data as you know to limit the query, (including the chipType).
 When a -1 is encountered or zero length chipType the query function will iterate on all possible values for that
 entry and return the relevant data.

 NOTE: the Valid flags of the ecmdChipTarget structure are not used for this function

 Ex: to query what positions of the Nova chip are on cage 1, node 2:
   cage = 1, node = 2, pos = -1, chipType = 'Nova', core = -1, thread = -1
 Ex: to query what positions of the Nova chip are in the entire system:
   cage = -1, node = -1, pos = -1, chipType = 'Nova', core = -1, thread = -1
 Ex: to query all the chips on cage 3, node 0:
   cage = 3, node = 0, pos = -1, chipType = '', core = -1, thread = -1
*/

int ecmdQueryConfig(ecmdChipTarget & target, vector<ecmdCageData> & queryData);

/**
 @brief Query Ring information from the DLL
 @param target Struct that contains chip and cage/node/position/core/thread information of chip to use
 @param queryData Return vector from query
 @param ringName if != NULL used to refine query to a single ring
 @retval ECMD_SUCCESS if successful
 @retval nonzero on failure
*/
int ecmdQueryRing(ecmdChipTarget & target, vector<ecmdRingData> & queryData, const char * ringName = NULL);

/**
 @brief Query Array information from the DLL
 @param target Struct that contains chip and cage/node/position/core/thread information of chip to use
 @param queryData Return vector from query
 @param arrayName array to access data for
 @retval ECMD_SUCCESS if successful
 @retval nonzero on failure
*/
int ecmdQueryArray(ecmdChipTarget & target, vector<ecmdArrayData> & queryData, const char * arrayName);

/**
 @brief Query Spy information from the DLL
 @param target Struct that contains chip and cage/node/position/core/thread information of chip to use
 @param queryData Return vector from query
 @param spyName Spy to access data for
 @retval ECMD_SUCCESS if successful
 @retval nonzero on failure
*/
int ecmdQuerySpy(ecmdChipTarget & target, vector<ecmdSpyData> & queryData, const char * spyName);

/**
 @brief Query the location of a specific file type for the selected target
 @param target Struct that contains chip and cage/node/position/core/thread information
 @param fileType Enum that specifies which type of file you are looking for scandef/spydef/arraydef
 @param fileLocation Return string with full path and filename to location
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
*/
int ecmdQueryFileLocation(ecmdChipTarget & target, ecmdFileType_t fileType, string fileLocation);

//@}

/** @name Scan Functions */
//@{
/**
 @brief Scans the selected number of bits from the selected position in the selected ring into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of ring to read
 @param ringName Name of ring to read from
 @param data DataBuffer object that holds data read from ring
 @see putRing

*/
int getRing (ecmdChipTarget & target, const char * ringName, ecmdDataBuffer & data);

/**
 @brief Scans the selected number of bits from the data buffer into the selected position in the selected ring
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of ring to write
 @param ringName Name of ring to write to
 @param data DataBuffer object that holds data to write into ring
 @see getRing

*/
int putRing (ecmdChipTarget & target, const char * ringName, ecmdDataBuffer & data);

/**
 @brief Scans all of the bits from the selected ring on the target into the selected file
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of ring to read
 @param ringName Name of ring to read from
 @param fileName Name of file to write data to
 @see ringWrite

 - comment on file format, naming convention, should we give it a default file name?

*/
int ringRead (ecmdChipTarget & target, const char * ringName, const char * fileName);

/**
 @brief Scans all of the bits from the given file into theselected ring on the target
 @retval ECMD_SUCCESS if successful write, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of ring to write
 @param ringName Name of ring to write to
 @param fileName Name of file to read data from
 @see ringRead

 - comment on file format, naming convention, should we give it a default file name?

*/
int ringWrite (ecmdChipTarget & target, const char * ringName, const char * fileName);

//@}

/** @name Scom Functions  */
//@{

/**
 @brief Scoms bits from the selected address into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of scom address to read
 @param address Scom address to read from
 @param data DataBuffer object that holds data read from address
 @see putScom

*/
int getScom (ecmdChipTarget & target, uint32_t address, ecmdDataBuffer & data);

/**
 @brief Scoms bits from the data buffer into the selected address
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of scom address to write
 @param address Scom address to write to
 @param data DataBuffer object that holds data to write into address
 @see getScom

*/
int putScom (ecmdChipTarget & target, uint32_t address, ecmdDataBuffer & data);

//@}

/** @name Spy Functions */
//@{

/**
 @brief Scans the selected number of bits from the selected position in the selected alias into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of alias to read
 @param aliasName Name of alias to read from
 @param data DataBuffer object that holds data read from alias
 @see putAlias

*/
int getSpy (ecmdChipTarget & target, const char * spyName, ecmdDataBuffer & data);

/**
 @brief Scans the selected number of bits from the selected position in the selected alias into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of alias to read
 @param aliasName Name of alias to read from
 @param enumValue Enum value
 @see putAlias

*/
int getSpyEnum (ecmdChipTarget & target, const char * spyName, string enumValue);

/**
 @brief Scans the selected number of bits from the data buffer into the selected position in the selected alias
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of alias to write
 @param aliasName Name of alias to write to
 @param data DataBuffer object that holds data to write into alias
 @see getAlias

*/
int putSpy (ecmdChipTarget & target, const char * spyName, ecmdDataBuffer & data);

/**
 @brief Scans the selected number of bits from the data buffer into the selected position in the selected alias
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of alias to write
 @param aliasName Name of alias to write to
 @param enumValue DataBuffer object that holds data to write into alias
 @see getAlias

*/
int putSpyEnum (ecmdChipTarget & target, const char * spyName, const string enumValue);

//@}

/** @name Array Functions */
//@{

/**
 @brief Reads bits from the selected array into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of array to read
 @param arrayName Name of array to read from
 @param data DataBuffer object that holds data read from address
 @see putArray

*/
int getArray (ecmdChipTarget & target, const char * arrayName, uint32_t * address, ecmdDataBuffer & data);

/**
 @brief Writes bits from the data buffer into the selected array
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of array to write
 @param arrayName Name of array to write to
 @param data DataBuffer object that holds data to write into array
 @see getArray

*/
int putArray (ecmdChipTarget & target, const char * arrayName, uint32_t * address, ecmdDataBuffer & data);

//@}

/** @name Flush and IPL Functions */
//@{

/**
 * @brief System Flush
 * @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 * @post The system is cleaned up and ready for iplsys
 * @see iplSys

*/
int flushSys ();

/**
 * @brief Initial Program Load
 * @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 * @pre An ecmdFlushSys call is generally required before iplsys
 * @post The system is IPLed
 * @see flushSys

*/
int iplSys ();

//@}

/** @name Error Handling Functions */
//@{

/**
 @brief Retrieve additional error information for errorcode
 @retval point to NULL terminated string containing error data, NULL if error occurs
*/
string ecmdGetErrorMsg(int errorCode);

/**
 @brief Register an Error Message that has occured
*/
int ecmdRegisterErrorMsg(int errorCode, const char* whom, const char* message);

//@}

/** @name Output Functions */
//@{

//@}

}  //extern "C"

#endif /* ecmdClientCapi_H */

// Change Log *********************************************************
//
//  Flag Reason   Vers Date     Coder  Description
//  ---- -------- ---- -------- -----  -------------------------------
//                              cengel Initial Creation
//
// End Change Log *****************************************************
<commit_msg>cleaned up the load functions, and output functions<commit_after>#ifndef ecmdClientCapi_H
#define ecmdClientCapi_H

/* $Header$ */

/**
 * @file ecmdClientCapi.H
 * @brief eCMD C/C++ Client Interface
*/

//--------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------
#include <ecmdReturnCodes.H>
#include <ecmdStructs.H>
#include <ecmdDataBuffer.H>

//--------------------------------------------------------------------
//  Forward References
//--------------------------------------------------------------------

/* Functions in here are defined as extern C for the following reasons:
 1)  Keeps Function names small by preventing C++ "mangling"
 2)  Allows (C-based) perl interpreter to access these functions

*/
extern "C" {

/** @name Load/Unload Functions */
//@{
/**
 @brief Load the eCMD DLL
 @param dllName Specify the full path and name of the dll to load,
 @retval ECMD_SUCCESS if successful load
 @retval ECMD_INVALID_DLL_VERSION if Dll version loaded doesn't match client version
 @retval nonzero if unsuccessful
 @post eCMD DLL is loaded into memory and initialized
 @see unloadDll

       - This function loads the DLL based on dllName if specified, otherwise the env var ECMD_DLL_FILE is used
       - Name limit of 255 characters.
       - Errors in loading are printed to STDOUT.
*/
int ecmdLoadDll(string dllName);

/**
 @brief Unload the eCMD DLL
 @retval ECMD_SUCCESS if successful unload
 @retval nonzero if unsuccessful
 @see loadDll

 - Errors in unloading are printed to STDOUT.
*/

int ecmdUnloadDll();

/**
 @brief Pass any unknown command line paramaters to the DLL for processing (ex. -p#, Cronus -debug)
 @retval ECMD_SUCCESS if successful
 @retval nonzero if unsuccessful
 @param argc Passed from Command line Arguments
 @param argv Passed from Command line Arguments
 @pre loadDll must have been called
 @post Global options (ex. -debug, -p#, -c#) will be removed from arg list
 @see loadDll

 - argc/argv get passed to the eCMD DLL.
 - Global options such as -debug flags and -p#, -c# will be parsed out.
 - Position flags can be queried later with functions like ?????
*/

int ecmdCommandArgs(int argc, char* argv[]);

//@}

/** @name Query Functions */
//@{
/**
 @brief Query configuration information from the DLL
 @param target Struct that contains partial information to limit query results
 @param queryData Return vector from query - in numerical order by cageId
 @retval ECMD_SUCCESS if successful
 @retval nonzero on failure

 The Valid bits of the target are used to refine the query

 The target paramater should be filled in with as much data as you know to limit the query, (including the chipType).
 When a field is nonValid the query function will iterate on all possible values for that
 entry and return the relevant data.

 Ex: to query what positions of the Nova chip are on cage 1, node 2:
   cage = 1, node = 2, pos = <nonvalid>, chipType = 'Nova', core = <nonvalid>, thread = <nonvalid>
 Ex: to query what positions of the Nova chip are in the entire system:
   cage = <nonvalid>, node = <nonvalid>, pos = <nonvalid>, chipType = 'Nova', core = <nonvalid>, thread = <nonvalid>
 Ex: to query all the chips on cage 3, node 0:
   cage = 3, node = 0, pos = <nonvalid>, chipType = <nonvalid>, core = <nonvalid>, thread = <nonvalid>
*/

int ecmdQueryConfig(ecmdChipTarget & target, vector<ecmdCageData> & queryData);

/**
 @brief Query Ring information from the DLL
 @param target Struct that contains chip and cage/node/position/core/thread information of chip to use
 @param queryData Return vector from query
 @param ringName if != NULL used to refine query to a single ring
 @retval ECMD_SUCCESS if successful
 @retval nonzero on failure
*/
int ecmdQueryRing(ecmdChipTarget & target, vector<ecmdRingData> & queryData, const char * ringName = NULL);

/**
 @brief Query Array information from the DLL
 @param target Struct that contains chip and cage/node/position/core/thread information of chip to use
 @param queryData Return vector from query
 @param arrayName array to access data for
 @retval ECMD_SUCCESS if successful
 @retval nonzero on failure
*/
int ecmdQueryArray(ecmdChipTarget & target, vector<ecmdArrayData> & queryData, const char * arrayName);

/**
 @brief Query Spy information from the DLL
 @param target Struct that contains chip and cage/node/position/core/thread information of chip to use
 @param queryData Return vector from query
 @param spyName Spy to access data for
 @retval ECMD_SUCCESS if successful
 @retval nonzero on failure
*/
int ecmdQuerySpy(ecmdChipTarget & target, vector<ecmdSpyData> & queryData, const char * spyName);

/**
 @brief Query the location of a specific file type for the selected target
 @param target Struct that contains chip and cage/node/position/core/thread information
 @param fileType Enum that specifies which type of file you are looking for scandef/spydef/arraydef
 @param fileLocation Return string with full path and filename to location
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
*/
int ecmdQueryFileLocation(ecmdChipTarget & target, ecmdFileType_t fileType, string fileLocation);

/**
 @brief Query wether the target specified was selected by the user with -n#, -p#, -c#, -t#
 @param target Struct that contains the cage/node/position/core/thread information (chipType not used)
 @retval FALSE if target not selected
 @retval TRUE if target selected
  - The Valid bits of the target are used to refine the query @see ecmdQueryConfig
*/
uint8_t ecmdQueryTargetSelected(ecmdChipTarget & target);

//@}

/** @name Scan Functions */
//@{
/**
 @brief Scans the selected number of bits from the selected position in the selected ring into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of ring to read
 @param ringName Name of ring to read from
 @param data DataBuffer object that holds data read from ring
 @see putRing

*/
int getRing (ecmdChipTarget & target, const char * ringName, ecmdDataBuffer & data);

/**
 @brief Scans the selected number of bits from the data buffer into the selected position in the selected ring
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of ring to write
 @param ringName Name of ring to write to
 @param data DataBuffer object that holds data to write into ring
 @see getRing

*/
int putRing (ecmdChipTarget & target, const char * ringName, ecmdDataBuffer & data);

/**
 @brief Scans all of the bits from the selected ring on the target into the selected file
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of ring to read
 @param ringName Name of ring to read from
 @param fileName Name of file to write data to
 @see ringWrite

 - comment on file format, naming convention, should we give it a default file name?

*/
int ringRead (ecmdChipTarget & target, const char * ringName, const char * fileName);

/**
 @brief Scans all of the bits from the given file into theselected ring on the target
 @retval ECMD_SUCCESS if successful write, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of ring to write
 @param ringName Name of ring to write to
 @param fileName Name of file to read data from
 @see ringRead

 - comment on file format, naming convention, should we give it a default file name?

*/
int ringWrite (ecmdChipTarget & target, const char * ringName, const char * fileName);

//@}

/** @name Scom Functions  */
//@{

/**
 @brief Scoms bits from the selected address into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of scom address to read
 @param address Scom address to read from
 @param data DataBuffer object that holds data read from address
 @see putScom

*/
int getScom (ecmdChipTarget & target, uint32_t address, ecmdDataBuffer & data);

/**
 @brief Scoms bits from the data buffer into the selected address
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of scom address to write
 @param address Scom address to write to
 @param data DataBuffer object that holds data to write into address
 @see getScom

*/
int putScom (ecmdChipTarget & target, uint32_t address, ecmdDataBuffer & data);

//@}

/** @name Spy Functions */
//@{

/**
 @brief Scans the selected number of bits from the selected position in the selected alias into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of alias to read
 @param spyName Name of alias to read from
 @param data DataBuffer object that holds data read from alias
 @see putAlias

*/
int getSpy (ecmdChipTarget & target, const char * spyName, ecmdDataBuffer & data);

/**
 @brief Scans the selected number of bits from the selected position in the selected alias into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of alias to read
 @param spyName Name of alias to read from
 @param enumValue Enum value
 @see putAlias

*/
int getSpyEnum (ecmdChipTarget & target, const char * spyName, string enumValue);

/**
 @brief Scans the selected number of bits from the data buffer into the selected position in the selected alias
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of alias to write
 @param spyName Name of alias to write to
 @param data DataBuffer object that holds data to write into alias
 @see getAlias

*/
int putSpy (ecmdChipTarget & target, const char * spyName, ecmdDataBuffer & data);

/**
 @brief Scans the selected number of bits from the data buffer into the selected position in the selected alias
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of alias to write
 @param spyName Name of alias to write to
 @param enumValue DataBuffer object that holds data to write into alias
 @see getAlias

*/
int putSpyEnum (ecmdChipTarget & target, const char * spyName, const string enumValue);

//@}

/** @name Array Functions */
//@{

/**
 @brief Reads bits from the selected array into the data buffer
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of array to read
 @param arrayName Name of array to read from
 @param data DataBuffer object that holds data read from address
 @param address Array Address to read from - how long is this ??????
 @see putArray

*/
int getArray (ecmdChipTarget & target, const char * arrayName, uint32_t * address, ecmdDataBuffer & data);

/**
 @brief Writes bits from the data buffer into the selected array
 @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 @param target Struct that contains chip and cage/node/position/core/thread information of array to write
 @param arrayName Name of array to write to
 @param data DataBuffer object that holds data to write into array
 @param address Array Address to write to - how long is this ??????
 @see getArray

*/
int putArray (ecmdChipTarget & target, const char * arrayName, uint32_t * address, ecmdDataBuffer & data);

//@}

/** @name Flush and IPL Functions */
//@{

/**
 * @brief System Flush
 * @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 * @post The system is cleaned up and ready for iplsys
 * @see iplSys

*/
int flushSys ();

/**
 * @brief Initial Program Load
 * @retval ECMD_SUCCESS if successful read, nonzero if unsuccessful
 * @pre An ecmdFlushSys call is generally required before iplsys
 * @post The system is IPLed
 * @see flushSys

*/
int iplSys ();

//@}

/** @name Error Handling Functions */
//@{

/**
 @brief Retrieve additional error information for errorcode
 @param errorCode Error code to lookup up message for
 @retval point to NULL terminated string containing error data, NULL if error occurs
*/
string ecmdGetErrorMsg(int errorCode);

/**
 @brief Register an Error Message that has occured
*/
int ecmdRegisterErrorMsg(int errorCode, const char* whom, const char* message);

//@}

/** @name Output Functions */
//@{

/**
 @brief Output a message related to an error
 @param message String to output
*/
void ecmdOutputError(const char* message);

/**
 @brief Output a message related to an warning
 @param message String to output
*/
void ecmdOutputWarning(const char* message);

/**
 @brief Output a message to the screen or logs
 @param message String to output
*/
void ecmdOutput(const char* message);

//@}

}  //extern "C"

#endif /* ecmdClientCapi_H */

/**
 * @mainpage

@section int Introduction

Common Hardware Access Programming Interface (eCMD)

This is the documentation of the eCMD C/C++ Programming Api

@section inc Include Files

To compile client code to use the C++ API, the following header files are required:
<ul>
<li> ecmdClientCapi.H
<li> ecmdDataBuffer.H
<li> ecmdStructs.H
<li> ecmdReturnCodes.H
</ul>

@section link Link objects
To link the client code on AIX, the following is required:
<ul>
<li>ecmdClientCapi_aix.a
<li>ecmdClientCapi.export
<li>xlC v5.0
</ul>
To create Linux x86 binaries, the following is required:
<ul>
<li>ecmdClientCapi_x86.a
<li>g++ v2.96
</ul>
To create Linux ppc binaries, the following is required:
<ul>
<li>ecmdClientCapi_ppc.a
<li>g++ ????
</ul>
@section dllv DLL Version
The eCMD Capi client code is built with a ECMD_CAPI_VERSION that gets passed into the DLL with the initDll function. If the version passed in does not match the version compiled into the DLL, the init will fail. The programmer needs to get a new copy of the .a archive and rebuild there client to correct this problem.

<br>
<hr>
@section bvc The ecmdDataBuffer class
Data is passed between the client and the DLL with the ecmdDataBuffer class.  The ecmdDataBuffer object is linked on both the client side and the DLL side.

The ecmdDataBuffer maintains data both as unsigned integers and as a character string.  The class contains methods for accessing and modifying data as well as converting data to strings (e.g. hex, left-aligned).  The ecmdDataBuffer class allocates the memory for the conversion-to-string routines and returns a char* pointer to the memory.  The client should allocate its own memory and do a strcpy if the string is to be preserved upon the next ecmdDataBuffer conversion-to-string call.
<br>
<hr>
@section makefile Makefile Example

@subsection Aixmake Aix
<ul>
<pre>
testclient: testclient.o ecmdClientCapi.H ecmdDataBuffer.H ecmdReturnCodes.H ecmdStructs.H ecmdClientCapi_aix.a
	xlC -+ -g testclient.o ecmdClientCapi_aix.a -bI:ecmdClientCapi.export -o testclient

testclient.o: testclient.c ecmdClientCapi.H ecmdDataBuffer.H ecmdReturnCodes.H ecmdStructs.H ecmdClientCapi_aix.a
	xlC -+ -g -c testclient.c -o testclient.o
</pre>
</ul>
@subsection Linuxmake Linux x86
<ul>
<pre>
testclient.linux: testclient_linux.o ecmdClientCapi.H ecmdDataBuffer.H ecmdReturnCodes.H ecmdStructs.H ecmdClientCapi_x86.a
	g++ -g -ldl testclient_linux.o ecmdClientCapi_x86.a -o testclient.linux

testclient_linux.o: testclient.c ecmdClientCapi.H ecmdDataBuffer.H ecmdReturnCodes.H ecmdStructs.H ecmdClientCapi_x86.a
	g++ -g -c -I./ testclient.c -o testclient_linux.o
</pre>
</ul>

*/

// Change Log *********************************************************
//
//  Flag Reason   Vers Date     Coder  Description
//  ---- -------- ---- -------- -----  -------------------------------
//                              cengel Initial Creation
//
// End Change Log *****************************************************
<|endoftext|>