<commit_before>#include "SDL.h"
#include <iostream>
#include <optional>

#include "core/log.h"
#include "core/str.h"
#include "core/interpolate.h"
#include "core/os.h"
#include "core/cint.h"
#include "core/ecs-systems.h"
#include "core/vfs_imagegenerator.h"
#include "core/vfs_defaultshaders.h"
#include "core/proto.h"
#include "core/viewportdef.h"
#include "core/sol.h"

#include "render/debuggl.h"
#include "render/font.h"
#include "render/init.h"
#include "render/fontcache.h"
#include "render/scalablesprite.h"
#include "render/shaderattribute2d.h"
#include "render/texturecache.h"
#include "render/viewport.h"
#include "render/viewporthandler.h"
#include "render/shader.h"
#include "render/spriterender.h"

#include "window/key.h"
#include "window/imguilibrary.h"
#include "window/imgui_extra.h"
#include "window/filesystem.h"
#include "window/sdllibrary.h"
#include "window/sdlwindow.h"
#include "window/sdlglcontext.h"
#include "window/engine.h"

#include "engine/loadworld.h"
#include "engine/systems.h"
#include "engine/dukintegration.h"
#include "engine/dukmathbindings.h"
#include "engine/dukprint.h"
#include "engine/input.h"
#include "engine/objectemplate.h"
#include "engine/components.h"
#include "engine/cameradata.h"

#include "imgui/imgui.h"

#include "gaf_game.h"
#include "gaf_pugixml_game.h"

using namespace euphoria::core;
using namespace euphoria::core::ecs;
using namespace euphoria::render;
using namespace euphoria::window;
using namespace euphoria::engine;

std::optional<game::Game>
load_game_data(vfs::FileSystem* fs)
{
    return get_optional_and_log_errors
    (
        read_xml_file_to_gaf_struct<::game::Game>
        (
            fs,
            vfs::FilePath{"~/gamedata.xml"},
            ::game::ReadXmlElementGame
        )
    );
}

struct RunResult
{
    bool ok;
    std::string message;

    [[nodiscard]]
    static
    RunResult
    create_ok()
    {
        return RunResult {true, ""};
    }

    [[nodiscard]]
    static
    RunResult
    create_error(const std::string& message)
    {
        return RunResult {false, message};
    }

private:
    RunResult(bool b, const std::string& str) : ok(b), message(str) {}
};

RunResult
run_main_script_file(LuaState* duk, vfs::FileSystem* fs, const vfs::FilePath& path)
{
    std::string content;
    const bool loaded = fs->read_file_to_string(path, &content);
    if(!loaded)
    {
        const std::string error_message = StringBuilder() << "Unable to open " << path
                                                << " for running";
        LOG_ERROR("{0}", error_message);
        return RunResult::create_error(error_message);
    }
    const auto eval = duk->state.script
    (
        content,
        [](lua_State*, sol::protected_function_result pfr) { return pfr; }
    );
    if(!eval.valid())
    {
        const sol::error err = eval;
        const std::string error_message = StringBuilder() << "Failed to run " << path << ": " << err.what();
        LOG_ERROR("{0}", error_message);
        return RunResult::create_error(error_message);
    }

    return RunResult::create_ok();
}

ViewportType
con(game::ViewportType type)
{
    switch(type)
    {
    case game::ViewportType::FitWithBlackBars:
        return ViewportType::fit_with_black_bars;
    case game::ViewportType::ScreenPixel:
        return ViewportType::screen_pixel;
    case game::ViewportType::Extend:
        return ViewportType::extend;
    default:
        DIE("Unhandled viewport case");
        return ViewportType::screen_pixel;
    }
}

Rgb
get_color(std::shared_ptr<game::Color> c)
{
    if(c == nullptr)
    {
        return NamedColor::gray;
    }

    if(c->hex != nullptr)
    {
        return Rgb::from_hex(colorutil::from_string_to_hex(*c->hex));
    }

    LOG_ERROR("Unable to parse color");
    return NamedColor::cornflower_blue;
}

int custom_lua_exception_handler
(
    lua_State* lua_state,
    sol::optional<const std::exception&>,
    sol::string_view description
)
{
    LOG_ERROR("An exception occurred in a function: {0}", description);

	// note that Lua -- and 99.5% of all Lua users and libraries -- expects a string
	// so we push a single string (in our case, the description of the error)
	return sol::stack::push(lua_state, description);
}

int
main(int argc, char* argv[])
{
    Engine engine;
    if(const auto ret = engine.setup(argparse::NameAndArguments::extract(argc, argv)); ret != 0)
    {
        return ret;
    }

    engine.file_system->set_write_root
    (
        std::make_shared<vfs::WriteRootPhysicalFolder>(get_current_directory())
    );

    TextureCache cache {engine.file_system.get()};

    auto loaded_gamedata = load_game_data(engine.file_system.get());
    if(loaded_gamedata.has_value() == false)
    {
        return -1;
    }
    game::Game gamedata = *loaded_gamedata;
    const auto clear_color = get_color(gamedata.clear_color);

    int window_width = 800;
    int window_height = 600;

    if
    (
        engine.create_window
        (
            gamedata.title,
            window_width,
            window_height,
            true
        ) == false
    )
    {
        return -1;
    }

    InputSystem input;

    for(const auto& bind: gamedata.binds)
    {
        auto key = to_key(bind.key);
        if(key == Key::invalid)
        {
            LOG_ERROR("Invalid key: {0}", bind.key);
            key = Key::unbound;
        }

        input.add(std::make_shared<BoundVar>(bind.name, key));
    }

    ShaderProgram shader;
    attributes2d::prebind_shader(&shader);
    shader.load(engine.file_system.get(), vfs::FilePath{"~/shaders/sprite"});
    SpriteRenderer renderer(&shader);
    FontCache font_cache {engine.file_system.get(), &cache};

    LuaState duk;

    // todo(Gustav): replace with duk reference
    std::string& crash_message_string = duk.error;
    bool& has_crashed = duk.has_error;

    auto crash_on_exception = [&](const std::exception& ex)
    {
        has_crashed = true;
        crash_message_string = ex.what();
        LOG_ERROR("{0}", crash_message_string);
    };

    duk.state.set_exception_handler(&custom_lua_exception_handler);
    duk.state.open_libraries(sol::lib::base, sol::lib::package);
    add_print(&duk);
    bind_math(&duk);
    InputSystem::bind(&duk);

    Systems systems;
    World world {&systems};
    Components components {&world.reg};
    add_systems(&systems, &components);
    ObjectCreator templates;
    load_templates_but_only_names(gamedata, &templates);
    CameraData camera_data;

    auto integration = ScriptIntegration
    {
        &systems,
        &world,
        &duk,
        &templates,
        &components,
        &camera_data
    };
    const auto error_run_main
            = run_main_script_file(&duk, engine.file_system.get(), vfs::FilePath{"~/main.lua"});
    if(!error_run_main.ok)
    {
        has_crashed = true;
        crash_message_string = error_run_main.message;
    }
    load_templates
    (
        gamedata,
        &templates,
        &integration.get_registry(),
        &cache,
        &components
    );

    use(&shader);
    shader.set_uniform(shader.get_uniform("image"), 0);

    auto viewport_handler = euphoria::render::ViewportHandler
    {
        engine.init.get(),
        &camera_data.screen
    };
    viewport_handler.add(&shader);
    viewport_handler.type = con(gamedata.viewport.type);
    viewport_handler.virtual_width = gamedata.viewport.width;
    viewport_handler.virtual_height = gamedata.viewport.height;

    viewport_handler.set_size(window_width, window_height);

    try
    {
        load_world
        (
            engine.file_system.get(),
            &world,
            &integration.get_registry(),
            vfs::FilePath{"~/world.xml"},
            &templates,
            &duk
        );
    }
    catch(const std::exception& ex)
    {
        crash_on_exception(ex);
    }

    Uint64 now = SDL_GetPerformanceCounter();
    Uint64 last = 0;

    SDL_StartTextInput();

    bool running = true;

    int window_mouse_x = 0;
    int window_mouse_y = 0;
    SDL_GetMouseState(&window_mouse_x, &window_mouse_y);
    bool mouse_lmb_down = false;

    integration.bind_keys(input);

    engine.init->use_2d();

    auto handle_events = [&]()
    {
        SDL_Event e;
        while(SDL_PollEvent(&e) != 0)
        {
            if(e.type == SDL_QUIT)
            {
                running = false;
            }
            if(engine.on_resize(e, &window_width, &window_height))
            {
                viewport_handler.set_size(window_width, window_height);
            }

            if(has_crashed)
            {
                imgui::process_imgui_events(&e);
                if(e.type == SDL_KEYUP)
                {
                    const auto key = to_key(e.key.keysym);
                    if(key == Key::escape)
                    {
                        running = false;
                    }
                }
            }
            else
            {
                if(e.type == SDL_MOUSEMOTION)
                {
                    window_mouse_x = e.motion.x;
                    window_mouse_y = e.motion.y;
                }
                else if(e.type == SDL_KEYUP || e.type == SDL_KEYDOWN)
                {
                    const bool down = e.type == SDL_KEYDOWN;
                    const auto key = to_key(e.key.keysym);
                    input.set_key_state(key, down ? 1.0f : 0.0f);
                }
                else if(e.type == SDL_MOUSEBUTTONDOWN
                        || e.type == SDL_MOUSEBUTTONUP)
                {
                    const bool down = e.type == SDL_MOUSEBUTTONDOWN;
                    window_mouse_x = e.button.x;
                    window_mouse_y = e.button.y;
                    if(e.button.button == SDL_BUTTON_LEFT)
                    {
                        mouse_lmb_down = down;
                    }
                }
                else if(e.type == SDL_TEXTINPUT)
                {
                    // const std::string& input = e.text.text;
                }
            }
        }
    };

    while(running)
    {
        last = now;
        now = SDL_GetPerformanceCounter();
        const float dt = euphoria::core::c_u64_to_float(now - last) / euphoria::core::c_u64_to_float(SDL_GetPerformanceFrequency());

        handle_events();
        engine.imgui->start_new_frame();

        if(!has_crashed)
        {
            try
            {
                world.update(dt);
            }
            catch(const std::exception& ex)
            {
                crash_on_exception(ex);
            }
        }

        input.update_state();

        if(has_crashed == false)
        {
            integration.bind_keys(input);
        }

        viewport_handler.clear_black();

        if(has_crashed)
        {
            // todo(Gustav): fix crash rendering, perhaps by using a debug gui or imgui
            // nothing much is required just a better overflow detection
            // when rendering the error, perhaps making the error more visible
            // though clicking around and debugging might be useful...
            engine.init->clear_screen(NamedColor::cornflower_blue);

            if(imgui::begin_fixed_overlay(Corner::center, "Crashed"))
            {
                ImGui::TextDisabled("%s", crash_message_string.c_str());
                if(ImGui::Button("Quit"))
                {
                    running = false;
                }
                ImGui::End();
            }
        }
        else
        {
            engine.init->clear_screen(clear_color);
            world.draw(&renderer);
        }

        imgui::imgui_render();
        SDL_GL_SwapWindow(engine.window->window);

        world.reg.remove_entities_tagged_for_removal();
    }

    return 0;
}\
<commit_msg>style: removed junk character<commit_after>#include "SDL.h"
#include <iostream>
#include <optional>

#include "core/log.h"
#include "core/str.h"
#include "core/interpolate.h"
#include "core/os.h"
#include "core/cint.h"
#include "core/ecs-systems.h"
#include "core/vfs_imagegenerator.h"
#include "core/vfs_defaultshaders.h"
#include "core/proto.h"
#include "core/viewportdef.h"
#include "core/sol.h"

#include "render/debuggl.h"
#include "render/font.h"
#include "render/init.h"
#include "render/fontcache.h"
#include "render/scalablesprite.h"
#include "render/shaderattribute2d.h"
#include "render/texturecache.h"
#include "render/viewport.h"
#include "render/viewporthandler.h"
#include "render/shader.h"
#include "render/spriterender.h"

#include "window/key.h"
#include "window/imguilibrary.h"
#include "window/imgui_extra.h"
#include "window/filesystem.h"
#include "window/sdllibrary.h"
#include "window/sdlwindow.h"
#include "window/sdlglcontext.h"
#include "window/engine.h"

#include "engine/loadworld.h"
#include "engine/systems.h"
#include "engine/dukintegration.h"
#include "engine/dukmathbindings.h"
#include "engine/dukprint.h"
#include "engine/input.h"
#include "engine/objectemplate.h"
#include "engine/components.h"
#include "engine/cameradata.h"

#include "imgui/imgui.h"

#include "gaf_game.h"
#include "gaf_pugixml_game.h"

using namespace euphoria::core;
using namespace euphoria::core::ecs;
using namespace euphoria::render;
using namespace euphoria::window;
using namespace euphoria::engine;

std::optional<game::Game>
load_game_data(vfs::FileSystem* fs)
{
    return get_optional_and_log_errors
    (
        read_xml_file_to_gaf_struct<::game::Game>
        (
            fs,
            vfs::FilePath{"~/gamedata.xml"},
            ::game::ReadXmlElementGame
        )
    );
}

struct RunResult
{
    bool ok;
    std::string message;

    [[nodiscard]]
    static
    RunResult
    create_ok()
    {
        return RunResult {true, ""};
    }

    [[nodiscard]]
    static
    RunResult
    create_error(const std::string& message)
    {
        return RunResult {false, message};
    }

private:
    RunResult(bool b, const std::string& str) : ok(b), message(str) {}
};

RunResult
run_main_script_file(LuaState* duk, vfs::FileSystem* fs, const vfs::FilePath& path)
{
    std::string content;
    const bool loaded = fs->read_file_to_string(path, &content);
    if(!loaded)
    {
        const std::string error_message = StringBuilder() << "Unable to open " << path
                                                << " for running";
        LOG_ERROR("{0}", error_message);
        return RunResult::create_error(error_message);
    }
    const auto eval = duk->state.script
    (
        content,
        [](lua_State*, sol::protected_function_result pfr) { return pfr; }
    );
    if(!eval.valid())
    {
        const sol::error err = eval;
        const std::string error_message = StringBuilder() << "Failed to run " << path << ": " << err.what();
        LOG_ERROR("{0}", error_message);
        return RunResult::create_error(error_message);
    }

    return RunResult::create_ok();
}

ViewportType
con(game::ViewportType type)
{
    switch(type)
    {
    case game::ViewportType::FitWithBlackBars:
        return ViewportType::fit_with_black_bars;
    case game::ViewportType::ScreenPixel:
        return ViewportType::screen_pixel;
    case game::ViewportType::Extend:
        return ViewportType::extend;
    default:
        DIE("Unhandled viewport case");
        return ViewportType::screen_pixel;
    }
}

Rgb
get_color(std::shared_ptr<game::Color> c)
{
    if(c == nullptr)
    {
        return NamedColor::gray;
    }

    if(c->hex != nullptr)
    {
        return Rgb::from_hex(colorutil::from_string_to_hex(*c->hex));
    }

    LOG_ERROR("Unable to parse color");
    return NamedColor::cornflower_blue;
}

int custom_lua_exception_handler
(
    lua_State* lua_state,
    sol::optional<const std::exception&>,
    sol::string_view description
)
{
    LOG_ERROR("An exception occurred in a function: {0}", description);

	// note that Lua -- and 99.5% of all Lua users and libraries -- expects a string
	// so we push a single string (in our case, the description of the error)
	return sol::stack::push(lua_state, description);
}

int
main(int argc, char* argv[])
{
    Engine engine;
    if(const auto ret = engine.setup(argparse::NameAndArguments::extract(argc, argv)); ret != 0)
    {
        return ret;
    }

    engine.file_system->set_write_root
    (
        std::make_shared<vfs::WriteRootPhysicalFolder>(get_current_directory())
    );

    TextureCache cache {engine.file_system.get()};

    auto loaded_gamedata = load_game_data(engine.file_system.get());
    if(loaded_gamedata.has_value() == false)
    {
        return -1;
    }
    game::Game gamedata = *loaded_gamedata;
    const auto clear_color = get_color(gamedata.clear_color);

    int window_width = 800;
    int window_height = 600;

    if
    (
        engine.create_window
        (
            gamedata.title,
            window_width,
            window_height,
            true
        ) == false
    )
    {
        return -1;
    }

    InputSystem input;

    for(const auto& bind: gamedata.binds)
    {
        auto key = to_key(bind.key);
        if(key == Key::invalid)
        {
            LOG_ERROR("Invalid key: {0}", bind.key);
            key = Key::unbound;
        }

        input.add(std::make_shared<BoundVar>(bind.name, key));
    }

    ShaderProgram shader;
    attributes2d::prebind_shader(&shader);
    shader.load(engine.file_system.get(), vfs::FilePath{"~/shaders/sprite"});
    SpriteRenderer renderer(&shader);
    FontCache font_cache {engine.file_system.get(), &cache};

    LuaState duk;

    // todo(Gustav): replace with duk reference
    std::string& crash_message_string = duk.error;
    bool& has_crashed = duk.has_error;

    auto crash_on_exception = [&](const std::exception& ex)
    {
        has_crashed = true;
        crash_message_string = ex.what();
        LOG_ERROR("{0}", crash_message_string);
    };

    duk.state.set_exception_handler(&custom_lua_exception_handler);
    duk.state.open_libraries(sol::lib::base, sol::lib::package);
    add_print(&duk);
    bind_math(&duk);
    InputSystem::bind(&duk);

    Systems systems;
    World world {&systems};
    Components components {&world.reg};
    add_systems(&systems, &components);
    ObjectCreator templates;
    load_templates_but_only_names(gamedata, &templates);
    CameraData camera_data;

    auto integration = ScriptIntegration
    {
        &systems,
        &world,
        &duk,
        &templates,
        &components,
        &camera_data
    };
    const auto error_run_main
            = run_main_script_file(&duk, engine.file_system.get(), vfs::FilePath{"~/main.lua"});
    if(!error_run_main.ok)
    {
        has_crashed = true;
        crash_message_string = error_run_main.message;
    }
    load_templates
    (
        gamedata,
        &templates,
        &integration.get_registry(),
        &cache,
        &components
    );

    use(&shader);
    shader.set_uniform(shader.get_uniform("image"), 0);

    auto viewport_handler = euphoria::render::ViewportHandler
    {
        engine.init.get(),
        &camera_data.screen
    };
    viewport_handler.add(&shader);
    viewport_handler.type = con(gamedata.viewport.type);
    viewport_handler.virtual_width = gamedata.viewport.width;
    viewport_handler.virtual_height = gamedata.viewport.height;

    viewport_handler.set_size(window_width, window_height);

    try
    {
        load_world
        (
            engine.file_system.get(),
            &world,
            &integration.get_registry(),
            vfs::FilePath{"~/world.xml"},
            &templates,
            &duk
        );
    }
    catch(const std::exception& ex)
    {
        crash_on_exception(ex);
    }

    Uint64 now = SDL_GetPerformanceCounter();
    Uint64 last = 0;

    SDL_StartTextInput();

    bool running = true;

    int window_mouse_x = 0;
    int window_mouse_y = 0;
    SDL_GetMouseState(&window_mouse_x, &window_mouse_y);
    bool mouse_lmb_down = false;

    integration.bind_keys(input);

    engine.init->use_2d();

    auto handle_events = [&]()
    {
        SDL_Event e;
        while(SDL_PollEvent(&e) != 0)
        {
            if(e.type == SDL_QUIT)
            {
                running = false;
            }
            if(engine.on_resize(e, &window_width, &window_height))
            {
                viewport_handler.set_size(window_width, window_height);
            }

            if(has_crashed)
            {
                imgui::process_imgui_events(&e);
                if(e.type == SDL_KEYUP)
                {
                    const auto key = to_key(e.key.keysym);
                    if(key == Key::escape)
                    {
                        running = false;
                    }
                }
            }
            else
            {
                if(e.type == SDL_MOUSEMOTION)
                {
                    window_mouse_x = e.motion.x;
                    window_mouse_y = e.motion.y;
                }
                else if(e.type == SDL_KEYUP || e.type == SDL_KEYDOWN)
                {
                    const bool down = e.type == SDL_KEYDOWN;
                    const auto key = to_key(e.key.keysym);
                    input.set_key_state(key, down ? 1.0f : 0.0f);
                }
                else if(e.type == SDL_MOUSEBUTTONDOWN
                        || e.type == SDL_MOUSEBUTTONUP)
                {
                    const bool down = e.type == SDL_MOUSEBUTTONDOWN;
                    window_mouse_x = e.button.x;
                    window_mouse_y = e.button.y;
                    if(e.button.button == SDL_BUTTON_LEFT)
                    {
                        mouse_lmb_down = down;
                    }
                }
                else if(e.type == SDL_TEXTINPUT)
                {
                    // const std::string& input = e.text.text;
                }
            }
        }
    };

    while(running)
    {
        last = now;
        now = SDL_GetPerformanceCounter();
        const float dt = euphoria::core::c_u64_to_float(now - last) / euphoria::core::c_u64_to_float(SDL_GetPerformanceFrequency());

        handle_events();
        engine.imgui->start_new_frame();

        if(!has_crashed)
        {
            try
            {
                world.update(dt);
            }
            catch(const std::exception& ex)
            {
                crash_on_exception(ex);
            }
        }

        input.update_state();

        if(has_crashed == false)
        {
            integration.bind_keys(input);
        }

        viewport_handler.clear_black();

        if(has_crashed)
        {
            // todo(Gustav): fix crash rendering, perhaps by using a debug gui or imgui
            // nothing much is required just a better overflow detection
            // when rendering the error, perhaps making the error more visible
            // though clicking around and debugging might be useful...
            engine.init->clear_screen(NamedColor::cornflower_blue);

            if(imgui::begin_fixed_overlay(Corner::center, "Crashed"))
            {
                ImGui::TextDisabled("%s", crash_message_string.c_str());
                if(ImGui::Button("Quit"))
                {
                    running = false;
                }
                ImGui::End();
            }
        }
        else
        {
            engine.init->clear_screen(clear_color);
            world.draw(&renderer);
        }

        imgui::imgui_render();
        SDL_GL_SwapWindow(engine.window->window);

        world.reg.remove_entities_tagged_for_removal();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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 <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/openni_camera/openni_driver.h>
#include <pcl/filters/approximate_voxel_grid.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/console/parse.h>
#include <pcl/common/time.h>

#define FPS_CALC(_WHAT_) \
do \
{ \
    static unsigned count = 0;\
    static double last = pcl::getTime ();\
    double now = pcl::getTime (); \
    ++count; \
    if (now - last >= 1.0) \
    { \
      std::cout << "Average framerate("<< _WHAT_ << "): " << double(count)/double(now - last) << " Hz" <<  std::endl; \
      count = 0; \
      last = now; \
    } \
}while(false)

template <typename PointType>
class OpenNIVoxelGrid
{
  public:
    typedef pcl::PointCloud<PointType> Cloud;
    typedef typename Cloud::Ptr CloudPtr;
    typedef typename Cloud::ConstPtr CloudConstPtr;

    OpenNIVoxelGrid (const std::string& device_id = "",
                     const std::string& field_name = "z", float min_v = 0, float max_v = 5.0,
                     float leaf_size_x = 0.01, float leaf_size_y = 0.01, float leaf_size_z = 0.01)
    : viewer ("PCL OpenNI VoxelGrid Viewer")
    , device_id_(device_id)
    {
      grid_.setLeafSize (leaf_size_x, leaf_size_y, leaf_size_z);
      grid_.setFilterFieldName (field_name);
      grid_.setFilterLimits (min_v, max_v);
    }

    void
    cloud_cb_ (const CloudConstPtr& cloud)
    {
      set (cloud);
    }

    void
    set (const CloudConstPtr& cloud)
    {
      //lock while we set our cloud;
      boost::mutex::scoped_lock lock (mtx_);
      cloud_  = cloud;
    }

    CloudPtr
    get ()
    {
      //lock while we swap our cloud and reset it.
      boost::mutex::scoped_lock lock (mtx_);
      CloudPtr temp_cloud (new Cloud);

      grid_.setInputCloud (cloud_);
      grid_.filter (*temp_cloud);

      return (temp_cloud);
    }

    void
    run ()
    {
      pcl::Grabber* interface = new pcl::OpenNIGrabber (device_id_);

      boost::function<void (const CloudConstPtr&)> f = boost::bind (&OpenNIVoxelGrid::cloud_cb_, this, _1);
      boost::signals2::connection c = interface->registerCallback (f);

      interface->start ();

      while (!viewer.wasStopped ())
      {
        if (cloud_)
        {
          FPS_CALC ("drawing");
          //the call to get() sets the cloud_ to null;
          viewer.showCloud (get ());
        }
      }

      interface->stop ();
    }

    pcl::ApproximateVoxelGrid<PointType> grid_;
    pcl::visualization::CloudViewer viewer;
    std::string device_id_;
    boost::mutex mtx_;
    CloudConstPtr cloud_;
};

void
usage (char ** argv)
{
  std::cout << "usage: " << argv[0] << " <device_id> <options>\n\n"
            << "where options are:\n         -minmax min-max  :: set the ApproximateVoxelGrid min-max cutting values (default: 0-5.0)\n"
            <<                     "         -field  X        :: use field/dimension 'X' to filter data on (default: 'z')\n"

            << "                             -leaf x, y, z  :: set the ApproximateVoxelGrid leaf size (default: 0.01)\n";

  openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance ();
  if (driver.getNumberDevices () > 0)
  {
    for (unsigned deviceIdx = 0; deviceIdx < driver.getNumberDevices (); ++deviceIdx)
    {
      cout << "Device: " << deviceIdx + 1 << ", vendor: " << driver.getVendorName (deviceIdx) << ", product: " << driver.getProductName (deviceIdx)
              << ", connected: " << (int)driver.getBus (deviceIdx) << " @ " << (int)driver.getAddress (deviceIdx) << ", serial number: \'" << driver.getSerialNumber (deviceIdx) << "\'" << endl;
      cout << "device_id may be #1, #2, ... for the first second etc device in the list or" << endl
           << "                 bus@address for the device connected to a specific usb-bus / address combination (works only in Linux) or" << endl
           << "                 <serial-number> (only in Linux and for devices which provide serial numbers)"  << endl;
    }
  }
  else
    cout << "No devices connected." << endl;
}

int
main (int argc, char ** argv)
{
  if (pcl::console::find_argument (argc, argv, "-h") != -1)
    usage (argv);

  double min_v = 0, max_v = 5.0;
  pcl::console::parse_2x_arguments (argc, argv, "-minmax", min_v, max_v, false);
  std::string field_name ("z");
  pcl::console::parse_argument (argc, argv, "-field", field_name);
  PCL_INFO ("Filtering data on %s between %f -> %f.\n", field_name.c_str (), min_v, max_v);
  double leaf_x = 0.01, leaf_y = 0.01, leaf_z = 0.01;
  pcl::console::parse_3x_arguments (argc, argv, "-leaf", leaf_x, leaf_y, leaf_z, false);
  PCL_INFO ("Using %f, %f, %f as a leaf size for VoxelGrid.\n", leaf_x, leaf_y, leaf_z);

  pcl::OpenNIGrabber grabber ("");
  if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgb> ())
  {
    OpenNIVoxelGrid<pcl::PointXYZRGB> v ("", field_name, min_v, max_v, leaf_x, leaf_y, leaf_z);
    v.run ();
  }
  else
  {
    OpenNIVoxelGrid<pcl::PointXYZ> v ("", field_name, min_v, max_v, leaf_x, leaf_y, leaf_z);
    v.run ();
  }

  return (0);
}
<commit_msg>fixed a compiler error<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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 <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/openni_camera/openni_driver.h>
#include <pcl/filters/approximate_voxel_grid.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/console/parse.h>
#include <pcl/common/time.h>

#define FPS_CALC(_WHAT_) \
do \
{ \
    static unsigned count = 0;\
    static double last = pcl::getTime ();\
    double now = pcl::getTime (); \
    ++count; \
    if (now - last >= 1.0) \
    { \
      std::cout << "Average framerate("<< _WHAT_ << "): " << double(count)/double(now - last) << " Hz" <<  std::endl; \
      count = 0; \
      last = now; \
    } \
}while(false)

template <typename PointType>
class OpenNIVoxelGrid
{
  public:
    typedef pcl::PointCloud<PointType> Cloud;
    typedef typename Cloud::Ptr CloudPtr;
    typedef typename Cloud::ConstPtr CloudConstPtr;

    OpenNIVoxelGrid (const std::string& device_id = "",
                     const std::string& field_name = "z", float min_v = 0, float max_v = 5.0,
                     float leaf_size_x = 0.01, float leaf_size_y = 0.01, float leaf_size_z = 0.01)
    : viewer ("PCL OpenNI VoxelGrid Viewer")
    , device_id_(device_id)
    {
      grid_.setLeafSize (leaf_size_x, leaf_size_y, leaf_size_z);
      //grid_.setFilterFieldName (field_name);
      //grid_.setFilterLimits (min_v, max_v);
    }

    void
    cloud_cb_ (const CloudConstPtr& cloud)
    {
      set (cloud);
    }

    void
    set (const CloudConstPtr& cloud)
    {
      //lock while we set our cloud;
      boost::mutex::scoped_lock lock (mtx_);
      cloud_  = cloud;
    }

    CloudPtr
    get ()
    {
      //lock while we swap our cloud and reset it.
      boost::mutex::scoped_lock lock (mtx_);
      CloudPtr temp_cloud (new Cloud);

      grid_.setInputCloud (cloud_);
      grid_.filter (*temp_cloud);

      return (temp_cloud);
    }

    void
    run ()
    {
      pcl::Grabber* interface = new pcl::OpenNIGrabber (device_id_);

      boost::function<void (const CloudConstPtr&)> f = boost::bind (&OpenNIVoxelGrid::cloud_cb_, this, _1);
      boost::signals2::connection c = interface->registerCallback (f);

      interface->start ();

      while (!viewer.wasStopped ())
      {
        if (cloud_)
        {
          FPS_CALC ("drawing");
          //the call to get() sets the cloud_ to null;
          viewer.showCloud (get ());
        }
      }

      interface->stop ();
    }

    pcl::ApproximateVoxelGrid<PointType> grid_;
    pcl::visualization::CloudViewer viewer;
    std::string device_id_;
    boost::mutex mtx_;
    CloudConstPtr cloud_;
};

void
usage (char ** argv)
{
  std::cout << "usage: " << argv[0] << " <device_id> <options>\n\n"
            << "where options are:\n         -minmax min-max  :: set the ApproximateVoxelGrid min-max cutting values (default: 0-5.0)\n"
            <<                     "         -field  X        :: use field/dimension 'X' to filter data on (default: 'z')\n"

            << "                             -leaf x, y, z  :: set the ApproximateVoxelGrid leaf size (default: 0.01)\n";

  openni_wrapper::OpenNIDriver& driver = openni_wrapper::OpenNIDriver::getInstance ();
  if (driver.getNumberDevices () > 0)
  {
    for (unsigned deviceIdx = 0; deviceIdx < driver.getNumberDevices (); ++deviceIdx)
    {
      cout << "Device: " << deviceIdx + 1 << ", vendor: " << driver.getVendorName (deviceIdx) << ", product: " << driver.getProductName (deviceIdx)
              << ", connected: " << (int)driver.getBus (deviceIdx) << " @ " << (int)driver.getAddress (deviceIdx) << ", serial number: \'" << driver.getSerialNumber (deviceIdx) << "\'" << endl;
      cout << "device_id may be #1, #2, ... for the first second etc device in the list or" << endl
           << "                 bus@address for the device connected to a specific usb-bus / address combination (works only in Linux) or" << endl
           << "                 <serial-number> (only in Linux and for devices which provide serial numbers)"  << endl;
    }
  }
  else
    cout << "No devices connected." << endl;
}

int
main (int argc, char ** argv)
{
  if (pcl::console::find_argument (argc, argv, "-h") != -1)
    usage (argv);

  double min_v = 0, max_v = 5.0;
  pcl::console::parse_2x_arguments (argc, argv, "-minmax", min_v, max_v, false);
  std::string field_name ("z");
  pcl::console::parse_argument (argc, argv, "-field", field_name);
  PCL_INFO ("Filtering data on %s between %f -> %f.\n", field_name.c_str (), min_v, max_v);
  double leaf_x = 0.01, leaf_y = 0.01, leaf_z = 0.01;
  pcl::console::parse_3x_arguments (argc, argv, "-leaf", leaf_x, leaf_y, leaf_z, false);
  PCL_INFO ("Using %f, %f, %f as a leaf size for VoxelGrid.\n", leaf_x, leaf_y, leaf_z);

  pcl::OpenNIGrabber grabber ("");
  if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgb> ())
  {
    OpenNIVoxelGrid<pcl::PointXYZRGB> v ("", field_name, min_v, max_v, leaf_x, leaf_y, leaf_z);
    v.run ();
  }
  else
  {
    OpenNIVoxelGrid<pcl::PointXYZ> v ("", field_name, min_v, max_v, leaf_x, leaf_y, leaf_z);
    v.run ();
  }

  return (0);
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// drop_test.cpp
//
// Identification: test/executor/drop_test.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <cstdio>

#include "gtest/gtest.h"

#include "catalog/catalog.h"
#include "catalog/database_catalog.h"
#include "common/harness.h"
#include "concurrency/transaction_manager_factory.h"
#include "executor/create_executor.h"
#include "executor/drop_executor.h"
#include "parser/postgresparser.h"
#include "planner/drop_plan.h"
#include "planner/plan_util.h"

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Catalog Tests
//===--------------------------------------------------------------------===//

class DropTests : public PelotonTest {};

TEST_F(DropTests, DroppingDatabase) {
  auto catalog = catalog::Catalog::GetInstance();
  catalog->Bootstrap();

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();

  catalog->CreateDatabase("test_db", txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  EXPECT_TRUE(catalog->GetDatabaseObject("test_db", txn).get() != NULL);
  txn_manager.CommitTransaction(txn);

  parser::DropStatement drop_statement(
      parser::DropStatement::EntityType::kDatabase);

  drop_statement.TryBindDatabaseName("test_db");

  planner::DropPlan drop_plan(&drop_statement);

  // Execute drop database
  txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));
  executor::DropExecutor DropDBExecutor(&drop_plan, context.get());
  DropDBExecutor.Init();
  DropDBExecutor.Execute();
  txn_manager.CommitTransaction(txn);

  // The database should be deleted now
  txn = txn_manager.BeginTransaction();
  EXPECT_ANY_THROW(
    catalog->GetDatabaseObject("test_db", txn);
  );
  txn_manager.CommitTransaction(txn);

}

TEST_F(DropTests, DroppingTable) {
  auto catalog = catalog::Catalog::GetInstance();
  catalog->Bootstrap();

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();
  // Insert a table first
  auto id_column = catalog::Column(
      type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER),
      "dept_id", true);
  auto name_column =
      catalog::Column(type::TypeId::VARCHAR, 32, "dept_name", false);

  std::unique_ptr<catalog::Schema> table_schema(
      new catalog::Schema({id_column, name_column}));
  std::unique_ptr<catalog::Schema> table_schema2(
      new catalog::Schema({id_column, name_column}));

  catalog->CreateDatabase("test_db", txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  catalog->CreateTable("test_db", "department_table", std::move(table_schema),
                       txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  catalog->CreateTable("test_db", "department_table_2",
                       std::move(table_schema2), txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  EXPECT_EQ(
      (int)catalog->GetDatabaseObject("test_db", txn)->GetTableObjects().size(),
      2);

  // Now dropping the table using the executer
  catalog->DropTable("test_db", "department_table", txn);
  EXPECT_EQ(
      (int)catalog->GetDatabaseObject("test_db", txn)->GetTableObjects().size(),
      1);

  // free the database just created
  catalog->DropDatabaseWithName("test_db", txn);
  txn_manager.CommitTransaction(txn);
}

TEST_F(DropTests, DroppingTrigger) {
  auto catalog = catalog::Catalog::GetInstance();
  catalog->Bootstrap();

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();

  // Create a table first
  auto id_column = catalog::Column(
      type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER),
      "dept_id", true);
  auto name_column =
      catalog::Column(type::TypeId::VARCHAR, 32, "dept_name", false);

  std::unique_ptr<catalog::Schema> table_schema(
      new catalog::Schema({id_column, name_column}));

  catalog->CreateDatabase("test_db", txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  catalog->CreateTable("test_db", "department_table", std::move(table_schema),
                       txn);
  txn_manager.CommitTransaction(txn);

  // Create a trigger
  auto parser = parser::PostgresParser::GetInstance();
  std::string query =
      "CREATE TRIGGER update_dept_name "
      "BEFORE UPDATE OF dept_name ON department_table "
      "EXECUTE PROCEDURE log_update_dept_name();";
  std::unique_ptr<parser::SQLStatementList> stmt_list(
      parser.BuildParseTree(query).release());
  EXPECT_TRUE(stmt_list->is_valid);
  EXPECT_EQ(StatementType::CREATE, stmt_list->GetStatement(0)->GetType());
  auto create_trigger_stmt =
      static_cast<parser::CreateStatement *>(stmt_list->GetStatement(0));

  create_trigger_stmt->TryBindDatabaseName("test_db");

  // Create plans
  planner::CreatePlan plan(create_trigger_stmt);
  // Execute the create trigger
  txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));
  executor::CreateExecutor createTriggerExecutor(&plan, context.get());
  createTriggerExecutor.Init();
  createTriggerExecutor.Execute();

  // Check the effect of creation
  storage::DataTable *target_table =
      catalog::Catalog::GetInstance()->GetTableWithName(
          "test_db", "department_table", txn);
  txn_manager.CommitTransaction(txn);
  EXPECT_EQ(1, target_table->GetTriggerNumber());
  trigger::Trigger *new_trigger = target_table->GetTriggerByIndex(0);
  EXPECT_EQ(new_trigger->GetTriggerName(), "update_dept_name");

  LOG_INFO("Create trigger finishes. Now drop it.");

  // Drop statement and drop plan
  parser::DropStatement drop_statement(
      parser::DropStatement::EntityType::kTrigger, "department_table",
      "update_dept_name");

  drop_statement.TryBindDatabaseName("test_db");

  planner::DropPlan drop_plan(&drop_statement);

  // Execute the create trigger
  txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context2(
      new executor::ExecutorContext(txn));
  executor::DropExecutor drop_executor(&drop_plan, context2.get());
  drop_executor.Init();
  drop_executor.Execute();
  txn_manager.CommitTransaction(txn);

  // Check the effect of drop
  // Most major check in this test case
  EXPECT_EQ(0, target_table->GetTriggerNumber());

  // Now dropping the table using the executer
  txn = txn_manager.BeginTransaction();
  catalog->DropTable("test_db", "department_table", txn);
  EXPECT_EQ(0, (int)catalog::Catalog::GetInstance()
                   ->GetDatabaseObject("test_db", txn)
                   ->GetTableObjects()
                   .size());
  txn_manager.CommitTransaction(txn);

  // free the database just created
  txn = txn_manager.BeginTransaction();
  catalog->DropDatabaseWithName("test_db", txn);
  txn_manager.CommitTransaction(txn);
}

}  // namespace test
}  // namespace peloton
<commit_msg>drop test db name refine<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// drop_test.cpp
//
// Identification: test/executor/drop_test.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <cstdio>

#include "gtest/gtest.h"

#include "catalog/catalog.h"
#include "catalog/database_catalog.h"
#include "common/harness.h"
#include "concurrency/transaction_manager_factory.h"
#include "executor/create_executor.h"
#include "executor/drop_executor.h"
#include "parser/postgresparser.h"
#include "planner/drop_plan.h"
#include "planner/plan_util.h"

namespace peloton {
namespace test {

#define TEST_DB_NAME "test_db"

//===--------------------------------------------------------------------===//
// Catalog Tests
//===--------------------------------------------------------------------===//

class DropTests : public PelotonTest {};

TEST_F(DropTests, DroppingDatabase) {
  auto catalog = catalog::Catalog::GetInstance();
  catalog->Bootstrap();

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();

  catalog->CreateDatabase(TEST_DB_NAME, txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  EXPECT_TRUE(catalog->GetDatabaseObject(TEST_DB_NAME, txn).get() != NULL);
  txn_manager.CommitTransaction(txn);

  parser::DropStatement drop_statement(
      parser::DropStatement::EntityType::kDatabase);

  drop_statement.TryBindDatabaseName(TEST_DB_NAME);

  planner::DropPlan drop_plan(&drop_statement);

  // Execute drop database
  txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));
  executor::DropExecutor DropDBExecutor(&drop_plan, context.get());
  DropDBExecutor.Init();
  DropDBExecutor.Execute();
  txn_manager.CommitTransaction(txn);

  // The database should be deleted now
  txn = txn_manager.BeginTransaction();
  EXPECT_ANY_THROW(
    catalog->GetDatabaseObject(TEST_DB_NAME, txn);
  );
  txn_manager.CommitTransaction(txn);

}

TEST_F(DropTests, DroppingTable) {
  auto catalog = catalog::Catalog::GetInstance();
  catalog->Bootstrap();

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();
  // Insert a table first
  auto id_column = catalog::Column(
      type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER),
      "dept_id", true);
  auto name_column =
      catalog::Column(type::TypeId::VARCHAR, 32, "dept_name", false);

  std::unique_ptr<catalog::Schema> table_schema(
      new catalog::Schema({id_column, name_column}));
  std::unique_ptr<catalog::Schema> table_schema2(
      new catalog::Schema({id_column, name_column}));

  catalog->CreateDatabase(TEST_DB_NAME, txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  catalog->CreateTable(TEST_DB_NAME, "department_table", std::move(table_schema),
                       txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  catalog->CreateTable(TEST_DB_NAME, "department_table_2",
                       std::move(table_schema2), txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  EXPECT_EQ(
      (int)catalog->GetDatabaseObject(TEST_DB_NAME, txn)->GetTableObjects().size(),
      2);

  // Now dropping the table using the executer
  catalog->DropTable(TEST_DB_NAME, "department_table", txn);
  EXPECT_EQ(
      (int)catalog->GetDatabaseObject(TEST_DB_NAME, txn)->GetTableObjects().size(),
      1);

  // free the database just created
  catalog->DropDatabaseWithName(TEST_DB_NAME, txn);
  txn_manager.CommitTransaction(txn);
}

TEST_F(DropTests, DroppingTrigger) {
  auto catalog = catalog::Catalog::GetInstance();
  catalog->Bootstrap();

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();

  // Create a table first
  auto id_column = catalog::Column(
      type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER),
      "dept_id", true);
  auto name_column =
      catalog::Column(type::TypeId::VARCHAR, 32, "dept_name", false);

  std::unique_ptr<catalog::Schema> table_schema(
      new catalog::Schema({id_column, name_column}));

  catalog->CreateDatabase(TEST_DB_NAME, txn);
  txn_manager.CommitTransaction(txn);

  txn = txn_manager.BeginTransaction();
  catalog->CreateTable(TEST_DB_NAME, "department_table", std::move(table_schema),
                       txn);
  txn_manager.CommitTransaction(txn);

  // Create a trigger
  auto parser = parser::PostgresParser::GetInstance();
  std::string query =
      "CREATE TRIGGER update_dept_name "
      "BEFORE UPDATE OF dept_name ON department_table "
      "EXECUTE PROCEDURE log_update_dept_name();";
  std::unique_ptr<parser::SQLStatementList> stmt_list(
      parser.BuildParseTree(query).release());
  EXPECT_TRUE(stmt_list->is_valid);
  EXPECT_EQ(StatementType::CREATE, stmt_list->GetStatement(0)->GetType());
  auto create_trigger_stmt =
      static_cast<parser::CreateStatement *>(stmt_list->GetStatement(0));

  create_trigger_stmt->TryBindDatabaseName(TEST_DB_NAME);

  // Create plans
  planner::CreatePlan plan(create_trigger_stmt);
  // Execute the create trigger
  txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context(
      new executor::ExecutorContext(txn));
  executor::CreateExecutor createTriggerExecutor(&plan, context.get());
  createTriggerExecutor.Init();
  createTriggerExecutor.Execute();

  // Check the effect of creation
  storage::DataTable *target_table =
      catalog::Catalog::GetInstance()->GetTableWithName(
          TEST_DB_NAME, "department_table", txn);
  txn_manager.CommitTransaction(txn);
  EXPECT_EQ(1, target_table->GetTriggerNumber());
  trigger::Trigger *new_trigger = target_table->GetTriggerByIndex(0);
  EXPECT_EQ(new_trigger->GetTriggerName(), "update_dept_name");

  LOG_INFO("Create trigger finishes. Now drop it.");

  // Drop statement and drop plan
  parser::DropStatement drop_statement(
      parser::DropStatement::EntityType::kTrigger, "department_table",
      "update_dept_name");

  drop_statement.TryBindDatabaseName(TEST_DB_NAME);

  planner::DropPlan drop_plan(&drop_statement);

  // Execute the create trigger
  txn = txn_manager.BeginTransaction();
  std::unique_ptr<executor::ExecutorContext> context2(
      new executor::ExecutorContext(txn));
  executor::DropExecutor drop_executor(&drop_plan, context2.get());
  drop_executor.Init();
  drop_executor.Execute();
  txn_manager.CommitTransaction(txn);

  // Check the effect of drop
  // Most major check in this test case
  EXPECT_EQ(0, target_table->GetTriggerNumber());

  // Now dropping the table using the executer
  txn = txn_manager.BeginTransaction();
  catalog->DropTable(TEST_DB_NAME, "department_table", txn);
  EXPECT_EQ(0, (int)catalog::Catalog::GetInstance()
                   ->GetDatabaseObject(TEST_DB_NAME, txn)
                   ->GetTableObjects()
                   .size());
  txn_manager.CommitTransaction(txn);

  // free the database just created
  txn = txn_manager.BeginTransaction();
  catalog->DropDatabaseWithName(TEST_DB_NAME, txn);
  txn_manager.CommitTransaction(txn);
}

}  // namespace test
}  // namespace peloton
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <mapnik/config.hpp>

#include <mapbox/mapnik-vector-tile/vector_tile_merc_tile.hpp>
#include <mapbox/mapnik-vector-tile/vector_tile_processor.hpp>
#include <mapbox/mapnik-vector-tile/vector_tile_compression.hpp>

#include <boost/python.hpp>

std::string create_mvt_merc(
    mapnik::Map const& map,
    std::uint64_t x,
    std::uint64_t y,
    std::uint64_t z,
    std::uint32_t tile_size,
    std::int32_t buffer_size,
    double scale_denom,
    int offset_x,
    int offset_y,
    bool style_level_filter)
{
    mapnik::vector_tile_impl::processor proc(map);
    mapnik::vector_tile_impl::merc_tile tile(proc.create_tile(
        x, y, z, tile_size, buffer_size, scale_denom,
        offset_x, offset_y, style_level_filter));
    return tile.get_buffer();
}

std::string compress_mvt(std::string const & input)
{
    std::string output;
    mapnik::vector_tile_impl::zlib_compress(input, output);
    return output;
}

void export_mvt()
{
    using namespace boost::python;

    def("create_mvt_merc", &create_mvt_merc,
        (arg("map"),
         arg("x"),
         arg("y"),
         arg("z"),
         arg("tile_size") = 4096,
         arg("buffer_size") = 0,
         arg("scale_denom") = 0.0,
         arg("offset_x") = 0,
         arg("offset_y") = 0,
         arg("style_level_filter") = false),
        "Creates MVT into a buffer\n"
        "mapnik.create_mvt_merc(m, 2257, 1393, 12, 4096, 0, 0, 0, 0)");

    def("compress_mvt", &compress_mvt,
        "gzip compression");
}
<commit_msg>mvt: expose more parameters<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <mapnik/config.hpp>

#include <mapbox/mapnik-vector-tile/vector_tile_merc_tile.hpp>
#include <mapbox/mapnik-vector-tile/vector_tile_processor.hpp>
#include <mapbox/mapnik-vector-tile/vector_tile_compression.hpp>

#define BOOST_PYTHON_MAX_ARITY 20
#include <boost/python.hpp>

std::string create_mvt_merc(
    mapnik::Map const& map,
    std::uint64_t x,
    std::uint64_t y,
    std::uint64_t z,
    std::uint32_t tile_size,
    std::int32_t buffer_size,
    double scale_denom,
    int offset_x,
    int offset_y,
    bool style_level_filter,
    double simplify_distance,
    double area_threshold,
    bool process_all_rings,
    bool multi_polygon_union,
    mapnik::vector_tile_impl::polygon_fill_type fill_type,
    std::string const& image_format,
    mapnik::scaling_method_e scaling_method,
    std::launch threading_mode
    )
{
    mapnik::vector_tile_impl::processor proc(map);

    proc.set_area_threshold(area_threshold);
    proc.set_simplify_distance(simplify_distance);
    proc.set_multi_polygon_union(multi_polygon_union);
    proc.set_process_all_rings(process_all_rings);
    proc.set_fill_type(fill_type);
    proc.set_image_format(image_format);
    proc.set_scaling_method(scaling_method);
    proc.set_threading_mode(threading_mode);

    mapnik::vector_tile_impl::merc_tile tile(proc.create_tile(
        x, y, z, tile_size, buffer_size, scale_denom,
        offset_x, offset_y, style_level_filter));
    return tile.get_buffer();
}

std::string compress_mvt(std::string const & input)
{
    std::string output;
    mapnik::vector_tile_impl::zlib_compress(input, output);
    return output;
}

void export_mvt()
{
    using namespace boost::python;

    using fill_type = mapnik::vector_tile_impl::polygon_fill_type;
    enum_<fill_type>("polygon_fill_type")
        .value("even_odd", fill_type::even_odd_fill)
        .value("non_zero", fill_type::non_zero_fill)
        .value("positive", fill_type::positive_fill)
        .value("negative", fill_type::negative_fill)
    ;

    enum_<std::launch>("threading_mode")
        .value("async", std::launch::async)
        .value("deferred", std::launch::deferred)
    ;

    def("create_mvt_merc", &create_mvt_merc,
        (arg("map"),
         arg("x"),
         arg("y"),
         arg("z"),
         arg("tile_size") = 4096,
         arg("buffer_size") = 0,
         arg("scale_denom") = 0.0,
         arg("offset_x") = 0,
         arg("offset_y") = 0,
         // Filter features by rule conditions in styles.
         arg("style_level_filter") = false,
         // Positive value in input projection will turn on
         // douglas-peucker with given simplification distance.
         arg("simplify_distance") = 0.0,
         // Skip polygons with area below this threshold,
         // in input projection.
         arg("area_threshold") = 0.1,
         // Process all rings even exterior ring is degenerated
         // or smaller than area_threshold.
         arg("process_all_rings") = false,
         // Conflate multi-polygon.
         arg("multi_polygon_union") = false,
         // Polygon fill strategy used during clipping.
         arg("fill_type") = fill_type::positive_fill,
         // Raster image format.
         arg("image_format") = std::string("webp"),
         // Raster scaling method.
         arg("scaling_method") = mapnik::SCALING_BILINEAR,
         // Allows parallel processing of layers.
         arg("threading_mode") = std::launch::deferred),
        "Creates MVT into a buffer\n"
        "mapnik.create_mvt_merc(m, 2257, 1393, 12, 4096, 0, 0, 0, 0)");

    def("compress_mvt", &compress_mvt,
        "gzip compression");
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
 * 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 the copyright holders 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.
 */

/*
 * $Id$
 *
 */

#ifndef MAP_H
#define MAP_H

#include "mem/gems_common/Vector.hh"

namespace __gnu_cxx {
  template <> struct hash <std::string>
  {
    size_t operator()(const string& s) const { return hash<char*>()(s.c_str()); }
  };
}

typedef unsigned long long uint64;
//hack for uint64 hashes...
namespace __gnu_cxx {
  template <> struct hash <uint64>
  {
    size_t operator()(const uint64 & s) const { return (size_t) s; }
  };
}

template <class KEY_TYPE, class VALUE_TYPE>
class Map
{
public:
  Map() { /* empty */ }
  ~Map() { /* empty */ }

  void add(const KEY_TYPE& key, const VALUE_TYPE& value);
  bool exist(const KEY_TYPE& key) const;
  int size() const { return m_map.size(); }
  void erase(const KEY_TYPE& key) { assert(exist(key)); m_map.erase(key); }
  Vector<KEY_TYPE> keys() const;
  Vector<VALUE_TYPE> values() const;
  void deleteKeys();
  void deleteValues();
  VALUE_TYPE& lookup(const KEY_TYPE& key) const;
  void clear() { m_map.clear(); }
  void print(ostream& out) const;

  // Synonyms
  void remove(const KEY_TYPE& key) { erase(key); }
  void deallocate(const KEY_TYPE& key) { erase(key); }
  void allocate(const KEY_TYPE& key) { add(key, VALUE_TYPE()); }
  void insert(const KEY_TYPE& key, const VALUE_TYPE& value) { add(key, value); }

  // Use default copy constructor and assignment operator
private:
  // Data members

  // m_map is declared mutable because some methods from the STL "map"
  // class that should be const are not.  Thus we define this as
  // mutable so we can still have conceptually const accessors.
  mutable __gnu_cxx::hash_map<KEY_TYPE, VALUE_TYPE> m_map;
};

template <class KEY_TYPE, class VALUE_TYPE>
ostream& operator<<(ostream& out, const Map<KEY_TYPE, VALUE_TYPE>& map);

// *********************

template <class KEY_TYPE, class VALUE_TYPE>
void Map<KEY_TYPE, VALUE_TYPE>::add(const KEY_TYPE& key, const VALUE_TYPE& value)
{
  // Update or add a new key/value pair
  m_map[key] = value;
}

template <class KEY_TYPE, class VALUE_TYPE>
bool Map<KEY_TYPE, VALUE_TYPE>::exist(const KEY_TYPE& key) const
{
  return (m_map.count(key) != 0);
}

template <class KEY_TYPE, class VALUE_TYPE>
VALUE_TYPE& Map<KEY_TYPE, VALUE_TYPE>::lookup(const KEY_TYPE& key) const
{
  assert(exist(key));
  return m_map[key];
}

template <class KEY_TYPE, class VALUE_TYPE>
Vector<KEY_TYPE> Map<KEY_TYPE, VALUE_TYPE>::keys() const
{
  Vector<KEY_TYPE> keys;
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    keys.insertAtBottom((*iter).first);
  }
  return keys;
}

template <class KEY_TYPE, class VALUE_TYPE>
Vector<VALUE_TYPE> Map<KEY_TYPE, VALUE_TYPE>::values() const
{
  Vector<VALUE_TYPE> values;
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  pair<KEY_TYPE, VALUE_TYPE> p;

  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    p = *iter;
    values.insertAtBottom(p.second);
  }
  return values;
}

template <class KEY_TYPE, class VALUE_TYPE>
void Map<KEY_TYPE, VALUE_TYPE>::deleteKeys()
{
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  pair<KEY_TYPE, VALUE_TYPE> p;

  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    p = *iter;
    delete p.first;
  }
}

template <class KEY_TYPE, class VALUE_TYPE>
void Map<KEY_TYPE, VALUE_TYPE>::deleteValues()
{
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  pair<KEY_TYPE, VALUE_TYPE> p;

  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    p = *iter;
    delete p.second;
  }
}

template <class KEY_TYPE, class VALUE_TYPE>
void Map<KEY_TYPE, VALUE_TYPE>::print(ostream& out) const
{
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  pair<KEY_TYPE, VALUE_TYPE> p;

  out << "[";
  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    // unparse each basic block
    p = *iter;
    out << " " << p.first << "=" << p.second;
  }
  out << " ]";
}

template <class KEY_TYPE, class VALUE_TYPE>
ostream& operator<<(ostream& out, const Map<KEY_TYPE, VALUE_TYPE>& map)
{
  map.print(out);
  return out;
}

#endif //MAP_H
<commit_msg>ruby: Make ruby's Map use hashmap.hh to simplify things.<commit_after>/*
 * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
 * 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 the copyright holders 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.
 */

/*
 * $Id$
 *
 */

#ifndef MAP_H
#define MAP_H

#include "base/hashmap.hh"
#include "mem/gems_common/Vector.hh"

template <class KEY_TYPE, class VALUE_TYPE>
class Map
{
public:
  Map() { /* empty */ }
  ~Map() { /* empty */ }

  void add(const KEY_TYPE& key, const VALUE_TYPE& value);
  bool exist(const KEY_TYPE& key) const;
  int size() const { return m_map.size(); }
  void erase(const KEY_TYPE& key) { assert(exist(key)); m_map.erase(key); }
  Vector<KEY_TYPE> keys() const;
  Vector<VALUE_TYPE> values() const;
  void deleteKeys();
  void deleteValues();
  VALUE_TYPE& lookup(const KEY_TYPE& key) const;
  void clear() { m_map.clear(); }
  void print(ostream& out) const;

  // Synonyms
  void remove(const KEY_TYPE& key) { erase(key); }
  void deallocate(const KEY_TYPE& key) { erase(key); }
  void allocate(const KEY_TYPE& key) { add(key, VALUE_TYPE()); }
  void insert(const KEY_TYPE& key, const VALUE_TYPE& value) { add(key, value); }

  // Use default copy constructor and assignment operator
private:
  // Data members

  // m_map is declared mutable because some methods from the STL "map"
  // class that should be const are not.  Thus we define this as
  // mutable so we can still have conceptually const accessors.
  mutable m5::hash_map<KEY_TYPE, VALUE_TYPE> m_map;
};

template <class KEY_TYPE, class VALUE_TYPE>
ostream& operator<<(ostream& out, const Map<KEY_TYPE, VALUE_TYPE>& map);

// *********************

template <class KEY_TYPE, class VALUE_TYPE>
void Map<KEY_TYPE, VALUE_TYPE>::add(const KEY_TYPE& key, const VALUE_TYPE& value)
{
  // Update or add a new key/value pair
  m_map[key] = value;
}

template <class KEY_TYPE, class VALUE_TYPE>
bool Map<KEY_TYPE, VALUE_TYPE>::exist(const KEY_TYPE& key) const
{
  return (m_map.count(key) != 0);
}

template <class KEY_TYPE, class VALUE_TYPE>
VALUE_TYPE& Map<KEY_TYPE, VALUE_TYPE>::lookup(const KEY_TYPE& key) const
{
  assert(exist(key));
  return m_map[key];
}

template <class KEY_TYPE, class VALUE_TYPE>
Vector<KEY_TYPE> Map<KEY_TYPE, VALUE_TYPE>::keys() const
{
  Vector<KEY_TYPE> keys;
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    keys.insertAtBottom((*iter).first);
  }
  return keys;
}

template <class KEY_TYPE, class VALUE_TYPE>
Vector<VALUE_TYPE> Map<KEY_TYPE, VALUE_TYPE>::values() const
{
  Vector<VALUE_TYPE> values;
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  pair<KEY_TYPE, VALUE_TYPE> p;

  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    p = *iter;
    values.insertAtBottom(p.second);
  }
  return values;
}

template <class KEY_TYPE, class VALUE_TYPE>
void Map<KEY_TYPE, VALUE_TYPE>::deleteKeys()
{
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  pair<KEY_TYPE, VALUE_TYPE> p;

  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    p = *iter;
    delete p.first;
  }
}

template <class KEY_TYPE, class VALUE_TYPE>
void Map<KEY_TYPE, VALUE_TYPE>::deleteValues()
{
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  pair<KEY_TYPE, VALUE_TYPE> p;

  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    p = *iter;
    delete p.second;
  }
}

template <class KEY_TYPE, class VALUE_TYPE>
void Map<KEY_TYPE, VALUE_TYPE>::print(ostream& out) const
{
  typename hash_map<KEY_TYPE, VALUE_TYPE>::const_iterator iter;
  pair<KEY_TYPE, VALUE_TYPE> p;

  out << "[";
  for (iter = m_map.begin(); iter != m_map.end(); iter++) {
    // unparse each basic block
    p = *iter;
    out << " " << p.first << "=" << p.second;
  }
  out << " ]";
}

template <class KEY_TYPE, class VALUE_TYPE>
ostream& operator<<(ostream& out, const Map<KEY_TYPE, VALUE_TYPE>& map)
{
  map.print(out);
  return out;
}

#endif //MAP_H
<|endoftext|>


<commit_before>#pragma warning(disable: 4244) // conversion, possible loss of data

#include <pwn/mesh/mesh.h>
#include <pwn/math/operations.h>
#include <pwn/core/stdutil.h>
#include <boost/foreach.hpp>
#include <pwn/assert.h>

#include <pwn/core/stdutil.h>
#include <fstream>

namespace pwn
{
	namespace mesh
	{
		real Timed::getTime() const
		{
			return time;
		}

		Timed::Timed(real t)
			: time(t)
		{
		}

		FramePosition::FramePosition()
			: Timed(0)
			, location(math::Origo3().vec)
		{
		}

		FramePosition::FramePosition(real time, const math::vec3& loc)
			: Timed(time)
			, location(loc)
		{
		}

		string FramePosition::toString() const
		{
			return core::Str() << getTime() << " " << location;
		}

		math::vec3 Interpolate(const FramePosition& from, real current, const FramePosition& to)
		{
			real scale = math::To01(from.getTime(), current, to.getTime());
			if (math::IsWithinInclusive(0, scale, 1) == false) throw "invalid scale";
			return math::Lerp(from.location, scale, to.location);
		}

		FrameRotation::FrameRotation()
			: Timed(0)
			, rotation(math::qIdentity())
		{
		}

		FrameRotation::FrameRotation(real time, const math::quat& rot)
			: Timed(time)
			, rotation(rot)
		{
		}

		string FrameRotation::toString() const
		{
			return core::Str() << getTime() << " " << math::cAxisAngle(rotation);
		}

		math::quat Interpolate(const FrameRotation& from, real current, const FrameRotation& to)
		{
			real scale = math::To01(from.getTime(), current, to.getTime());
			if (math::IsWithinInclusive(0, scale, 1) == false) throw "invalid scale";
			return math::SlerpShortway(from.rotation, scale, to.rotation);
		}

		PosePerBone::PosePerBone()
			: location(math::Origo3().vec)
			, rotation(math::qIdentity())
		{
		}

		PosePerBone::PosePerBone(math::vec3 l, math::quat r)
			: location(l)
			, rotation(r)
		{
		}

		string PosePerBone::toString() const
		{
			return core::Str() << location << ": " << math::cAxisAngle(rotation);
		}

		math::quat Interpolate(real time, const std::vector<FrameRotation>& fr)
		{
			const int fri = Get(fr, time);
			if (fri == -1) return math::qIdentity();
			const math::quat r( Interpolate(fr[fri - 1], time, fr[fri]) );
			return r;
		}

		math::vec3 Interpolate(real time, const std::vector<FramePosition>& fp)
		{
			const int fpi = Get(fp, time);
			if (fpi == -1) return math::Origo3().vec;
			const math::vec3 res( Interpolate(fp[fpi - 1], time, fp[fpi]) );
			return res;
		}

		AnimationPerBone::AnimationPerBone()
		{
		}

		AnimationPerBone::AnimationPerBone(std::vector<FramePosition>& afp, std::vector<FrameRotation>& afr)
		{
			fp = afp;
			fr = afr;
		}

		void AnimationPerBone::addPosition(real time, const math::vec3& pos)
		{
			fp.push_back(FramePosition(time, pos));
		}

		void AnimationPerBone::addRotation(real time, const math::quat& q)
		{
			fr.push_back(FrameRotation(time, q));
		}

		string AnimationPerBone::toString() const
		{
			return core::Str() << "<" << fp.size() << " " << fr.size() << ">";
		}

		real AnimationPerBone::getLength() const
		{
			// get the time of the last frame
			return fp[fp.size() - 1].getTime();
		}

		PosePerBone AnimationPerBone::getBonePose(real time) const
		{
			const PosePerBone p(
				Interpolate(time, fp),
				Interpolate(time, fr) );
			return p;
		}

		void AnimationPerBone::sub(int start, int end, AnimationPerBone* out) const
		{
			std::vector<FramePosition> abfp;
			std::vector<FrameRotation> abfr;
			real length = end - start;
			bool first = true;
			real last = 0;

			for(std::size_t i=0; i<this->fp.size(); ++i)
			{
				const FramePosition& fp = this->fp[i];
				if (math::IsWithinInclusive(start, fp.getTime(), end))
				{
					real mark = fp.getTime()-start;
					if (first && math::IsZero(mark)==false)
					{
						abfp.push_back(FramePosition(0, Interpolate(start, this->fp)));
					}
					mark = math::ZeroOrValue(mark);
					first = false;
					abfp.push_back(FramePosition(mark, fp.location));
					last = mark;
				}
			}
			if (math::IsEqual(length, last)==false )
			{
				abfp.push_back(FramePosition(length, Interpolate(end, this->fp)));
			}

			first = true;
			last = 0;

			for(std::size_t i=0; i<this->fr.size(); ++i)
			{
				const FrameRotation& fr = this->fr[i];
				if (math::IsWithinInclusive(start, fr.getTime(), end))
				{
					real mark = fr.getTime() - start;
					if (first && math::IsZero(mark) == false)
					{
						abfr.push_back(FrameRotation(0, Interpolate(start, this->fr)));
					}
					mark = math::ZeroOrValue(mark);
					first = false;
					abfr.push_back(FrameRotation(mark, fr.rotation));
					last = mark;
				}
			}
			if (math::IsEqual(length, last) == false)
			{
				abfr.push_back(FrameRotation(length, Interpolate(end, this->fr)));
			}

			if (abfp.size() < 2 || abfr.size() < 2) throw "Data error, need atleast 2 keyframes per animation";
			out->fp = abfp;
			out->fr = abfr;
		}

		void AnimationPerBone::scale(real scale)
		{
			for(std::size_t i=0; i<fp.size(); ++i)
			{
				FramePosition& f = fp[i];
				f.location *= scale;
			}
		}

		CompiledPose::CompiledPose()
		{
		}

		namespace
		{
			void dump(const pwn::string& file, const math::mat44& p)
			{
				std::ofstream of(file.c_str());
				for(int r=0; r<4; ++r)
				{
					for(int c=0; c<4; ++c)
					{
						of << p.at(r, c) << " ";
					}
					of << std::endl;
				}
			}

			void dump(const pwn::string& file, const pwn::mesh::Bone& b)
			{
				std::ofstream of(file.c_str());

				of << b.rot.x << " "
					 << b.rot.y << " "
					 << b.rot.z << " "
					 << b.rot.w << std::endl;

				of << b.pos.x << " "
					 << b.pos.y << " "
					 << b.pos.z << std::endl;
			}
		}

		CompiledPose::CompiledPose(const Pose& pose, const std::vector<Bone>& bones)
		{
			if (pose.bones.size() != bones.size()) throw "Invalid animation/mesh, bone count differs";
			std::vector<math::mat44> result( pose.bones.size() );
			for (std::size_t boneIndex = 0; boneIndex < pose.bones.size(); ++boneIndex)
			{
				const Bone& bone = bones[boneIndex];
				// either it is a parent, or it's parent has already been precoessed
				Assert( bone.hasParent()==false || boneIndex > bone.getParent() );
				math::mat44 parent = bone.hasParent() ? result[bone.getParent()] : math::mat44Identity();
				const math::vec3 poseloc = pose.bones[boneIndex].location;
				const math::quat poserot = pose.bones[boneIndex].rotation;

				const math::mat44 anim = math::mat44helper(math::mat44Identity()).translate(poseloc).rotate(-poserot).mat;
				const math::mat44 skel = math::mat44helper(math::mat44Identity()).translate(bone.pos).rotate(bone.rot).mat;
				const math::mat44 local = math::mat44helper(math::mat44Identity()).mult(anim).mult(skel).mat;

				{
					using namespace pwn::math;
					using namespace pwn::mesh;
					using namespace pwn::core;
					dump(Str() << "C:\\Users\\Gustav\\dev\\pwn-engine\\dist\\temp\\pwn\\a0 bone " << boneIndex << ".txt", bone);
					dump(Str() << "C:\\Users\\Gustav\\dev\\pwn-engine\\dist\\temp\\pwn\\b anim " << boneIndex << ".txt", anim);
					dump(Str() << "C:\\Users\\Gustav\\dev\\pwn-engine\\dist\\temp\\pwn\\c skel " << boneIndex << ".txt", skel);
					dump(Str() << "C:\\Users\\Gustav\\dev\\pwn-engine\\dist\\temp\\pwn\\d local " << boneIndex << ".txt", local);
				}

				//result[boneIndex] = math::mat44helper(parent).rotate(bone.rot).translate(bone.pos).translate(poseloc).rotate(-poserot).mat;
				result[boneIndex] = math::mat44helper(parent).mult(local).mat;
			}
			transforms = result;
		}

		AnimationInformation::AnimationInformation(int s, int e, const string& n)
			: start(s)
			, end(e)
			, name(n)
		{
		}

		real CalculateLength(const std::vector<AnimationPerBone>& bones)
		{
			real length = 0;
			for(std::size_t i=0; i<bones.size(); ++i)
			{
				const AnimationPerBone& ab = bones[i];
				length = math::Max(length, ab.getLength());
			}
			return length;
		}

		Animation::Animation()
			: length(0)
		{
		}

		Animation::Animation(const std::vector<AnimationPerBone>& abones)
			: length( CalculateLength(abones) )
			, bones(abones)
		{
		}

		void Animation::getPose(real time, Pose* out) const
		{
			std::vector<PosePerBone> bd;
			bd.resize(bones.size());
			for(std::size_t i=0; i<bones.size(); ++i)
			{
				const AnimationPerBone& ab = bones[i];
				bd[i] = ab.getBonePose(time);
			}
			out->bones = bd;
		}

		real Animation::getLength() const
		{
			return length;
		}

		void Animation::subanim(int start, int end, Animation* out) const
		{
			std::vector<AnimationPerBone> bd(bones.size());
			for(std::size_t i=0; i<bones.size(); ++i)
			{
				const AnimationPerBone& ab = bones[i];
				ab.sub(start, end, &bd[i]);
			}
			out->bones = bd;
			out->length = CalculateLength(bd);
		}

		void Animation::subanim(const AnimationInformation& info, Animation* out) const
		{
			subanim(info.start, info.end, out);
		}

		void Animation::scale(real scale)
		{
			for(std::size_t i=0; i<bones.size(); ++i)
			{
				AnimationPerBone& ab = bones[i];
				ab.scale(scale);
			}
		}
	}
}
<commit_msg>final fix, correctly multiplying matrix<commit_after>#pragma warning(disable: 4244) // conversion, possible loss of data

#include <pwn/mesh/mesh.h>
#include <pwn/math/operations.h>
#include <pwn/core/stdutil.h>
#include <boost/foreach.hpp>
#include <pwn/assert.h>

#include <pwn/core/stdutil.h>
#include <fstream>

namespace pwn
{
	namespace mesh
	{
		real Timed::getTime() const
		{
			return time;
		}

		Timed::Timed(real t)
			: time(t)
		{
		}

		FramePosition::FramePosition()
			: Timed(0)
			, location(math::Origo3().vec)
		{
		}

		FramePosition::FramePosition(real time, const math::vec3& loc)
			: Timed(time)
			, location(loc)
		{
		}

		string FramePosition::toString() const
		{
			return core::Str() << getTime() << " " << location;
		}

		math::vec3 Interpolate(const FramePosition& from, real current, const FramePosition& to)
		{
			real scale = math::To01(from.getTime(), current, to.getTime());
			if (math::IsWithinInclusive(0, scale, 1) == false) throw "invalid scale";
			return math::Lerp(from.location, scale, to.location);
		}

		FrameRotation::FrameRotation()
			: Timed(0)
			, rotation(math::qIdentity())
		{
		}

		FrameRotation::FrameRotation(real time, const math::quat& rot)
			: Timed(time)
			, rotation(rot)
		{
		}

		string FrameRotation::toString() const
		{
			return core::Str() << getTime() << " " << math::cAxisAngle(rotation);
		}

		math::quat Interpolate(const FrameRotation& from, real current, const FrameRotation& to)
		{
			real scale = math::To01(from.getTime(), current, to.getTime());
			if (math::IsWithinInclusive(0, scale, 1) == false) throw "invalid scale";
			return math::SlerpShortway(from.rotation, scale, to.rotation);
		}

		PosePerBone::PosePerBone()
			: location(math::Origo3().vec)
			, rotation(math::qIdentity())
		{
		}

		PosePerBone::PosePerBone(math::vec3 l, math::quat r)
			: location(l)
			, rotation(r)
		{
		}

		string PosePerBone::toString() const
		{
			return core::Str() << location << ": " << math::cAxisAngle(rotation);
		}

		math::quat Interpolate(real time, const std::vector<FrameRotation>& fr)
		{
			const int fri = Get(fr, time);
			if (fri == -1) return math::qIdentity();
			const math::quat r( Interpolate(fr[fri - 1], time, fr[fri]) );
			return r;
		}

		math::vec3 Interpolate(real time, const std::vector<FramePosition>& fp)
		{
			const int fpi = Get(fp, time);
			if (fpi == -1) return math::Origo3().vec;
			const math::vec3 res( Interpolate(fp[fpi - 1], time, fp[fpi]) );
			return res;
		}

		AnimationPerBone::AnimationPerBone()
		{
		}

		AnimationPerBone::AnimationPerBone(std::vector<FramePosition>& afp, std::vector<FrameRotation>& afr)
		{
			fp = afp;
			fr = afr;
		}

		void AnimationPerBone::addPosition(real time, const math::vec3& pos)
		{
			fp.push_back(FramePosition(time, pos));
		}

		void AnimationPerBone::addRotation(real time, const math::quat& q)
		{
			fr.push_back(FrameRotation(time, q));
		}

		string AnimationPerBone::toString() const
		{
			return core::Str() << "<" << fp.size() << " " << fr.size() << ">";
		}

		real AnimationPerBone::getLength() const
		{
			// get the time of the last frame
			return fp[fp.size() - 1].getTime();
		}

		PosePerBone AnimationPerBone::getBonePose(real time) const
		{
			const PosePerBone p(
				Interpolate(time, fp),
				Interpolate(time, fr) );
			return p;
		}

		void AnimationPerBone::sub(int start, int end, AnimationPerBone* out) const
		{
			std::vector<FramePosition> abfp;
			std::vector<FrameRotation> abfr;
			real length = end - start;
			bool first = true;
			real last = 0;

			for(std::size_t i=0; i<this->fp.size(); ++i)
			{
				const FramePosition& fp = this->fp[i];
				if (math::IsWithinInclusive(start, fp.getTime(), end))
				{
					real mark = fp.getTime()-start;
					if (first && math::IsZero(mark)==false)
					{
						abfp.push_back(FramePosition(0, Interpolate(start, this->fp)));
					}
					mark = math::ZeroOrValue(mark);
					first = false;
					abfp.push_back(FramePosition(mark, fp.location));
					last = mark;
				}
			}
			if (math::IsEqual(length, last)==false )
			{
				abfp.push_back(FramePosition(length, Interpolate(end, this->fp)));
			}

			first = true;
			last = 0;

			for(std::size_t i=0; i<this->fr.size(); ++i)
			{
				const FrameRotation& fr = this->fr[i];
				if (math::IsWithinInclusive(start, fr.getTime(), end))
				{
					real mark = fr.getTime() - start;
					if (first && math::IsZero(mark) == false)
					{
						abfr.push_back(FrameRotation(0, Interpolate(start, this->fr)));
					}
					mark = math::ZeroOrValue(mark);
					first = false;
					abfr.push_back(FrameRotation(mark, fr.rotation));
					last = mark;
				}
			}
			if (math::IsEqual(length, last) == false)
			{
				abfr.push_back(FrameRotation(length, Interpolate(end, this->fr)));
			}

			if (abfp.size() < 2 || abfr.size() < 2) throw "Data error, need atleast 2 keyframes per animation";
			out->fp = abfp;
			out->fr = abfr;
		}

		void AnimationPerBone::scale(real scale)
		{
			for(std::size_t i=0; i<fp.size(); ++i)
			{
				FramePosition& f = fp[i];
				f.location *= scale;
			}
		}

		CompiledPose::CompiledPose()
		{
		}

		namespace
		{
			void dump(const pwn::string& file, const math::mat44& p)
			{
				std::ofstream of(file.c_str());
				for(int r=0; r<4; ++r)
				{
					for(int c=0; c<4; ++c)
					{
						of << p.at(r, c) << " ";
					}
					of << std::endl;
				}
			}

			void dump(const pwn::string& file, const pwn::mesh::Bone& b)
			{
				std::ofstream of(file.c_str());

				of << b.rot.x << " "
					 << b.rot.y << " "
					 << b.rot.z << " "
					 << b.rot.w << std::endl;

				of << b.pos.x << " "
					 << b.pos.y << " "
					 << b.pos.z << std::endl;
			}
		}

		CompiledPose::CompiledPose(const Pose& pose, const std::vector<Bone>& bones)
		{
			if (pose.bones.size() != bones.size()) throw "Invalid animation/mesh, bone count differs";
			std::vector<math::mat44> result( pose.bones.size() );
			for (std::size_t boneIndex = 0; boneIndex < pose.bones.size(); ++boneIndex)
			{
				const Bone& bone = bones[boneIndex];
				// either it is a parent, or it's parent has already been precoessed
				Assert( bone.hasParent()==false || boneIndex > bone.getParent() );
				math::mat44 parent = bone.hasParent() ? result[bone.getParent()] : math::mat44Identity();
				const math::vec3 poseloc = pose.bones[boneIndex].location;
				const math::quat poserot = pose.bones[boneIndex].rotation;

				const math::mat44 anim = math::mat44helper(math::mat44Identity()).translate(poseloc).rotate(-poserot).mat;
				const math::mat44 skel = math::mat44helper(math::mat44Identity()).translate(bone.pos).rotate(bone.rot).mat;
				const math::mat44 local = math::mat44helper(math::mat44Identity()).mult(skel).mult(anim).mat;

				{
					using namespace pwn::math;
					using namespace pwn::mesh;
					using namespace pwn::core;
					dump(Str() << "C:\\Users\\Gustav\\dev\\pwn-engine\\dist\\temp\\pwn\\a0 bone " << boneIndex << ".txt", bone);
					dump(Str() << "C:\\Users\\Gustav\\dev\\pwn-engine\\dist\\temp\\pwn\\b anim " << boneIndex << ".txt", anim);
					dump(Str() << "C:\\Users\\Gustav\\dev\\pwn-engine\\dist\\temp\\pwn\\c skel " << boneIndex << ".txt", skel);
					dump(Str() << "C:\\Users\\Gustav\\dev\\pwn-engine\\dist\\temp\\pwn\\d local " << boneIndex << ".txt", local);
				}

				//result[boneIndex] = math::mat44helper(parent).rotate(bone.rot).translate(bone.pos).translate(poseloc).rotate(-poserot).mat;
				result[boneIndex] = math::mat44helper(parent).mult(local).mat;
			}
			transforms = result;
		}

		AnimationInformation::AnimationInformation(int s, int e, const string& n)
			: start(s)
			, end(e)
			, name(n)
		{
		}

		real CalculateLength(const std::vector<AnimationPerBone>& bones)
		{
			real length = 0;
			for(std::size_t i=0; i<bones.size(); ++i)
			{
				const AnimationPerBone& ab = bones[i];
				length = math::Max(length, ab.getLength());
			}
			return length;
		}

		Animation::Animation()
			: length(0)
		{
		}

		Animation::Animation(const std::vector<AnimationPerBone>& abones)
			: length( CalculateLength(abones) )
			, bones(abones)
		{
		}

		void Animation::getPose(real time, Pose* out) const
		{
			std::vector<PosePerBone> bd;
			bd.resize(bones.size());
			for(std::size_t i=0; i<bones.size(); ++i)
			{
				const AnimationPerBone& ab = bones[i];
				bd[i] = ab.getBonePose(time);
			}
			out->bones = bd;
		}

		real Animation::getLength() const
		{
			return length;
		}

		void Animation::subanim(int start, int end, Animation* out) const
		{
			std::vector<AnimationPerBone> bd(bones.size());
			for(std::size_t i=0; i<bones.size(); ++i)
			{
				const AnimationPerBone& ab = bones[i];
				ab.sub(start, end, &bd[i]);
			}
			out->bones = bd;
			out->length = CalculateLength(bd);
		}

		void Animation::subanim(const AnimationInformation& info, Animation* out) const
		{
			subanim(info.start, info.end, out);
		}

		void Animation::scale(real scale)
		{
			for(std::size_t i=0; i<bones.size(); ++i)
			{
				AnimationPerBone& ab = bones[i];
				ab.scale(scale);
			}
		}
	}
}
<|endoftext|>


<commit_before>#include <functional>
#include <future>
#include "kernel.h"
#include "raster.h"
#include "symboltable.h"
#include "ilwisoperation.h"
#include "pixeliterator.h"
#include "gridinterpolator.h"
#include "resampleraster.h"

using namespace Ilwis;
using namespace BaseOperations;

Ilwis::OperationImplementation *ResampleRaster::create(quint64 metaid, const Ilwis::OperationExpression &expr)
{
    return new ResampleRaster(metaid, expr);
}

ResampleRaster::ResampleRaster()
{
}

ResampleRaster::ResampleRaster(quint64 metaid, const Ilwis::OperationExpression &expr) :
    OperationImplementation(metaid, expr),
    _method(GridCoverage::ipBICUBIC)
{
}

bool ResampleRaster::execute(ExecutionContext *ctx, SymbolTable& symTable)
{
    if (_prepState == sNOTPREPARED)
        if((_prepState = prepare(ctx,symTable)) != sPREPARED)
            return false;

    BoxedAsyncFunc resampleFun = [&](const Box3D<qint32>& box) -> bool {
        PixelIterator iterOut(_outputGC,box);
        GridInterpolator interpolator(_inputGC, _method);
        while(iterOut != iterOut.end()) {
           Voxel position = iterOut.position();
           Coordinate c = _outputGC->georeference()->pixel2Coord(Pixel_d(position.x(),(position.y())));
           Coordinate c2 = _inputGC->coordinateSystem()->coord2coord(_outputGC->coordinateSystem(),c);
           *iterOut = interpolator.coord2value(c2);
            ++iterOut;
        }
        return true;
    };

    bool res = OperationHelper::execute(ctx, resampleFun, _outputGC);

    if ( res && ctx != 0) {
        QVariant value;
        value.setValue<IGridCoverage>(_outputGC);
        ctx->addOutput(symTable,value,_outputGC->name(), itGRIDCOVERAGE, _outputGC->source() );
    }
    return res;
}

Ilwis::OperationImplementation::State ResampleRaster::prepare(ExecutionContext *, const SymbolTable & )
{
    QString gc = _expression.parm(0).value();
    QString outputName = _expression.parm(0,false).value();

    if (!_inputGC.prepare(gc)) {
        ERROR2(ERR_COULD_NOT_LOAD_2,gc,"");
        return sPREPAREFAILED;
    }
    _box = OperationHelper::initialize(_inputGC, _outputGC, _expression.parm(0),itDOMAIN);
    if ( !_outputGC.isValid()) {
        ERROR1(ERR_NO_INITIALIZED_1, "output gridcoverage");
        return sPREPAREFAILED;
    }
    IGeoReference grf;
    grf.prepare(_expression.parm(1).value());
    if ( !grf.isValid()) {
        return sPREPAREFAILED;
    }
    _outputGC->georeference(grf);
    Box2Dd env = grf->pixel2Coord(grf->size());
    _outputGC->envelope(env);
    if ( outputName != sUNDEF)
        _outputGC->setName(outputName);

    QString method = _expression.parm(2).value();
    if ( method.toLower() == "nearestneighbour")
        _method = GridCoverage::ipNEARESTNEIGHBOUR;
    else if ( method.toLower() == "bilinear")
        _method = GridCoverage::ipBILINEAR;
    else if (  method.toLower() == "bicubic")
        _method =GridCoverage::ipBICUBIC;
    else {
        ERROR3(ERR_ILLEGAL_PARM_3,"method",method,"resample");
        return sPREPAREFAILED;
    }

    return sPREPARED;
}

quint64 ResampleRaster::createMetadata()
{
    QString url = QString("ilwis://operations/resample");
    Resource res(QUrl(url), itOPERATIONMETADATA);
    res.addProperty("namespace","ilwis");
    res.addProperty("longname","resample");
    res.addProperty("syntax","resample(inputgridcoverage,targetgeoref,nearestneighbour|bilinear|bicubic)");
    res.addProperty("inparameters","3");
    res.addProperty("pin_1_type", itGRIDCOVERAGE);
    res.addProperty("pin_1_name", TR("input gridcoverage"));
    res.addProperty("pin_1_desc",TR("input gridcoverage with domain any domain"));
    res.addProperty("pin_2_type", itGEOREF);
    res.addProperty("pin_2_name", TR("target georeference"));
    res.addProperty("pin_2_desc",TR("the georeference to which the input coverage will be morphed"));
    res.addProperty("pin_3_type", itSTRING);
    res.addProperty("pin_3_name", TR("Resampling method"));
    res.addProperty("pin_3_desc",TR("The method used to aggregate pixels from the input map in the geometry of the output map"));
    res.addProperty("outparameters",1);
    res.addProperty("pout_1_type", itGRIDCOVERAGE);
    res.addProperty("pout_1_name", TR("output gridcoverage"));
    res.addProperty("pout_1_desc",TR("output gridcoverage with the domain of the input map"));
    res.prepare();
    url += "=" + QString::number(res.id());
    res.setUrl(url);

    mastercatalog()->addItems({res});
    return res.id();
}

<commit_msg>checks output value now against the range; might cost a little bit performance but ensure correct output ranges<commit_after>#include <functional>
#include <future>
#include "kernel.h"
#include "raster.h"
#include "symboltable.h"
#include "ilwisoperation.h"
#include "gridinterpolator.h"
#include "resampleraster.h"

using namespace Ilwis;
using namespace BaseOperations;

Ilwis::OperationImplementation *ResampleRaster::create(quint64 metaid, const Ilwis::OperationExpression &expr)
{
    return new ResampleRaster(metaid, expr);
}

ResampleRaster::ResampleRaster()
{
}

ResampleRaster::ResampleRaster(quint64 metaid, const Ilwis::OperationExpression &expr) :
    OperationImplementation(metaid, expr),
    _method(GridCoverage::ipBICUBIC)
{
}

bool ResampleRaster::execute(ExecutionContext *ctx, SymbolTable& symTable)
{
    if (_prepState == sNOTPREPARED)
        if((_prepState = prepare(ctx,symTable)) != sPREPARED)
            return false;

    BoxedAsyncFunc resampleFun = [&](const Box3D<qint32>& box) -> bool {
        PixelIterator iterOut(_outputGC,box);
        GridInterpolator interpolator(_inputGC, _method);
        SPRange range = _inputGC->datadef().range();
        while(iterOut != iterOut.end()) {
           Voxel position = iterOut.position();
           Coordinate c = _outputGC->georeference()->pixel2Coord(Pixel_d(position.x(),(position.y())));
           Coordinate c2 = _inputGC->coordinateSystem()->coord2coord(_outputGC->coordinateSystem(),c);
           double v = interpolator.coord2value(c2);
           *iterOut = range->ensure(v);
            ++iterOut;
        }
        return true;
    };

    bool res = OperationHelper::execute(ctx, resampleFun, _outputGC);

    if ( res && ctx != 0) {
        QVariant value;
        value.setValue<IGridCoverage>(_outputGC);
        ctx->addOutput(symTable,value,_outputGC->name(), itGRIDCOVERAGE, _outputGC->source() );
    }
    return res;
}

Ilwis::OperationImplementation::State ResampleRaster::prepare(ExecutionContext *, const SymbolTable & )
{
    QString gc = _expression.parm(0).value();
    QString outputName = _expression.parm(0,false).value();

    if (!_inputGC.prepare(gc)) {
        ERROR2(ERR_COULD_NOT_LOAD_2,gc,"");
        return sPREPAREFAILED;
    }
    _box = OperationHelper::initialize(_inputGC, _outputGC, _expression.parm(0),itDOMAIN);
    if ( !_outputGC.isValid()) {
        ERROR1(ERR_NO_INITIALIZED_1, "output gridcoverage");
        return sPREPAREFAILED;
    }
    IGeoReference grf;
    grf.prepare(_expression.parm(1).value());
    if ( !grf.isValid()) {
        return sPREPAREFAILED;
    }
    _outputGC->georeference(grf);
    Box2Dd env = grf->pixel2Coord(grf->size());
    _outputGC->envelope(env);
    if ( outputName != sUNDEF)
        _outputGC->setName(outputName);

    QString method = _expression.parm(2).value();
    if ( method.toLower() == "nearestneighbour")
        _method = GridCoverage::ipNEARESTNEIGHBOUR;
    else if ( method.toLower() == "bilinear")
        _method = GridCoverage::ipBILINEAR;
    else if (  method.toLower() == "bicubic")
        _method =GridCoverage::ipBICUBIC;
    else {
        ERROR3(ERR_ILLEGAL_PARM_3,"method",method,"resample");
        return sPREPAREFAILED;
    }

    return sPREPARED;
}

quint64 ResampleRaster::createMetadata()
{
    QString url = QString("ilwis://operations/resample");
    Resource res(QUrl(url), itOPERATIONMETADATA);
    res.addProperty("namespace","ilwis");
    res.addProperty("longname","resample");
    res.addProperty("syntax","resample(inputgridcoverage,targetgeoref,nearestneighbour|bilinear|bicubic)");
    res.addProperty("inparameters","3");
    res.addProperty("pin_1_type", itGRIDCOVERAGE);
    res.addProperty("pin_1_name", TR("input gridcoverage"));
    res.addProperty("pin_1_desc",TR("input gridcoverage with domain any domain"));
    res.addProperty("pin_2_type", itGEOREF);
    res.addProperty("pin_2_name", TR("target georeference"));
    res.addProperty("pin_2_desc",TR("the georeference to which the input coverage will be morphed"));
    res.addProperty("pin_3_type", itSTRING);
    res.addProperty("pin_3_name", TR("Resampling method"));
    res.addProperty("pin_3_desc",TR("The method used to aggregate pixels from the input map in the geometry of the output map"));
    res.addProperty("outparameters",1);
    res.addProperty("pout_1_type", itGRIDCOVERAGE);
    res.addProperty("pout_1_name", TR("output gridcoverage"));
    res.addProperty("pout_1_desc",TR("output gridcoverage with the domain of the input map"));
    res.prepare();
    url += "=" + QString::number(res.id());
    res.setUrl(url);

    mastercatalog()->addItems({res});
    return res.id();
}

<|endoftext|>