<commit_before>#include <cassert>
#include <cmath>
#include <vector>

#include "Player.h"

#include "EntityType.h"
#include "GenderName.h"
#include "../Game/Game.h"
#include "../Game/GameData.h"
#include "../Items/WeaponType.h"
#include "../Math/Constants.h"
#include "../Utilities/String.h"
#include "../World/VoxelData.h"
#include "../World/VoxelGrid.h"

const double Player::HEIGHT = 0.70;
const double Player::STEPPING_HEIGHT = 0.25;
const double Player::JUMP_VELOCITY = 3.0;
const double Player::GRAVITY = 9.81;
const double Player::FRICTION = 4.0;

Player::Player(const std::string &displayName, GenderName gender, int raceID,
	const CharacterClass &charClass, int portraitID, const Double3 &position,
	const Double3 &direction, const Double3 &velocity, double maxWalkSpeed,
	double maxRunSpeed, WeaponType weaponType)
	: displayName(displayName), gender(gender), raceID(raceID), charClass(charClass),
	portraitID(portraitID), camera(position, direction), velocity(velocity),
	maxWalkSpeed(maxWalkSpeed), maxRunSpeed(maxRunSpeed), weaponAnimation(weaponType)
{
	assert(portraitID >= 0);
}

Player::~Player()
{

}

const Double3 &Player::getPosition() const
{
	return this->camera.position;
}

const std::string &Player::getDisplayName() const
{
	return this->displayName;
}

std::string Player::getFirstName() const
{
	std::vector<std::string> nameTokens = String::split(this->displayName);
	return nameTokens.at(0);
}

int Player::getPortraitID() const
{
	return this->portraitID;
}

GenderName Player::getGenderName() const
{
	return this->gender;
}

int Player::getRaceID() const
{
	return this->raceID;
}

const CharacterClass &Player::getCharacterClass() const
{
	return this->charClass;
}

const Double3 &Player::getDirection() const
{
	return this->camera.getDirection();
}

const Double3 &Player::getRight() const
{
	return this->camera.getRight();
}

Double2 Player::getGroundDirection() const
{
	const Double3 &direction = this->camera.getDirection();
	return Double2(direction.x, direction.z).normalized();
}

double Player::getJumpMagnitude() const
{
	return Player::JUMP_VELOCITY;
}

WeaponAnimation &Player::getWeaponAnimation()
{
	return this->weaponAnimation;
}

Int3 Player::getVoxelPosition() const
{
	return Int3(
		static_cast<int>(std::floor(this->camera.position.x)),
		static_cast<int>(std::floor(this->camera.position.y)),
		static_cast<int>(std::floor(this->camera.position.z)));
}

double Player::getFeetY() const
{
	return this->camera.position.y - Player::HEIGHT;
}

bool Player::onGround(const VoxelGrid &voxelGrid) const
{
	// To do: find a non-hack way to do this.

	return true;

	// This function seems kind of like a hack right now, since the player's feet
	// will frequently be at Y == 1.0, which is one voxel above the ground, and
	// it won't be considered as "on ground" unless it checks the voxel underneath
	// of this particular Y position (due to the rounding rules being used).
	/*const double feetY = this->getFeetY();
	const double feetVoxelYPos = std::floor(feetY);
	const bool closeEnoughToLowerVoxel = std::abs(feetY - feetVoxelYPos) < EPSILON;
	const Int3 feetVoxel(
		static_cast<int>(std::floor(this->camera.position.x)),
		static_cast<int>(feetVoxelYPos) - (closeEnoughToLowerVoxel ? 1 : 0),
		static_cast<int>(std::floor(this->camera.position.z)));

	const bool insideWorld = [&feetVoxel, &voxelGrid]()
	{
		return (feetVoxel.x >= 0) && (feetVoxel.x < voxelGrid.getWidth()) &&
			(feetVoxel.y >= 0) && (feetVoxel.y < voxelGrid.getHeight()) &&
			(feetVoxel.z >= 0) && (feetVoxel.z < voxelGrid.getDepth());
	}();

	// Don't try to dereference the voxel grid if the player's feet are outside.
	if (insideWorld)
	{
		const char feetVoxelID = voxelGrid.getVoxels()[feetVoxel.x +
			(feetVoxel.y * voxelGrid.getWidth()) +
			(feetVoxel.z * voxelGrid.getWidth() * voxelGrid.getHeight())];
		const VoxelData &voxelData = voxelGrid.getVoxelData(feetVoxelID);

		return (this->velocity.y == 0.0) && !voxelData.isAir() &&
			(feetY >= (feetVoxelYPos + voxelData.yOffset)) &&
			(feetY <= (feetVoxelYPos + voxelData.yOffset + voxelData.ySize));
	}
	else return false;*/
}

void Player::teleport(const Double3 &position)
{
	this->camera.position = position;
}

void Player::rotate(double dx, double dy, double hSensitivity, double vSensitivity)
{
	// Multiply sensitivities by 100 so the values in options.txt are nicer.
	this->camera.rotate(dx * (100.0 * hSensitivity), dy * (100.0 * vSensitivity));
}

void Player::lookAt(const Double3 &point)
{
	this->camera.lookAt(point);
}

void Player::handleCollision(const VoxelGrid &voxelGrid, double dt)
{
	auto getVoxel = [&voxelGrid](int x, int y, int z)
	{
		// Voxels outside the world are air.
		if ((x < 0) || (x >= voxelGrid.getWidth()) ||
			(y < 0) || (y >= voxelGrid.getHeight()) ||
			(z < 0) || (z >= voxelGrid.getDepth()))
		{
			return VoxelData(0);
		}
		else
		{
			return voxelGrid.getVoxelData(voxelGrid.getVoxels()[x +
				(y * voxelGrid.getWidth()) +
				(z * voxelGrid.getWidth() * voxelGrid.getHeight())]);
		}
	};

	const double feetY = this->getFeetY();

	// Coordinates of the base of the voxel the feet are in.
	const double feetVoxelYPos = std::floor(feetY + (this->velocity.y * dt));

	// Get the voxel data for each voxel the player would touch on each axis.
	const Int3 playerVoxel = this->getVoxelPosition();
	const VoxelData &xVoxel = getVoxel(
		static_cast<int>(std::floor(this->camera.position.x + (this->velocity.x * dt))),
		playerVoxel.y,
		playerVoxel.z);
	const VoxelData &yVoxel = getVoxel(
		playerVoxel.x,
		static_cast<int>(feetVoxelYPos),
		playerVoxel.z);
	const VoxelData &zVoxel = getVoxel(
		playerVoxel.x,
		playerVoxel.y,
		static_cast<int>(std::floor(this->camera.position.z + (this->velocity.z * dt))));

	// Check horizontal collisions.

	// -- Temp hack until Y collision detection is implemented --
	auto isBridge = [](const VoxelData &voxel)
	{
		return (voxel.sideID == 42) && (voxel.floorID == 43) &&
			(voxel.ceilingID == 43);
	};

	if (!xVoxel.isAir() && !isBridge(xVoxel))
	{
		this->velocity.x = 0.0;
	}

	if (!zVoxel.isAir() && !isBridge(zVoxel))
	{
		this->velocity.z = 0.0;
	}
	// -- end hack --

	/*if (!xVoxel.isAir())
	{
		this->velocity.x = 0.0;
	}

	if (!zVoxel.isAir())
	{
		this->velocity.z = 0.0;
	}*/

	// To do: Y collision (snap Y position above ground if inside ground?).
	this->velocity.y = 0.0;

	// To do: use an axis-aligned bounding box or cylinder instead of a point?
}

void Player::accelerate(const Double3 &direction, double magnitude,
	bool isRunning, double dt)
{
	assert(dt >= 0.0);
	assert(magnitude >= 0.0);
	assert(std::isfinite(magnitude));
	assert(direction.isNormalized());

	// Simple Euler integration for updating velocity.
	Double3 newVelocity = this->velocity + (direction * (magnitude * dt));

	if (std::isfinite(newVelocity.length()))
	{
		this->velocity = newVelocity;
	}

	// Don't let the horizontal velocity be greater than the max speed for the
	// current movement state (i.e., walking/running).
	double maxSpeed = isRunning ? this->maxRunSpeed : this->maxWalkSpeed;
	Double2 velocityXZ(this->velocity.x, this->velocity.z);
	if (velocityXZ.length() > maxSpeed)
	{
		velocityXZ = velocityXZ.normalized() * maxSpeed;
	}

	// If the velocity is near zero, set it to zero. This fixes a problem where
	// the velocity could remain at a tiny magnitude and never reach zero.
	if (this->velocity.length() < 0.001)
	{
		this->velocity = Double3(0.0, 0.0, 0.0);
	}
}

void Player::accelerateInstant(const Double3 &direction, double magnitude)
{
	assert(direction.isNormalized());

	const Double3 additiveVelocity = direction * magnitude;

	if (std::isfinite(additiveVelocity.length()))
	{
		this->velocity = this->velocity + additiveVelocity;
	}
}

void Player::updatePhysics(const VoxelGrid &voxelGrid, double dt)
{
	// Acceleration from gravity (always).
	this->accelerate(-Double3::UnitY, Player::GRAVITY, false, dt);

	// Change the player's velocity based on collision.
	this->handleCollision(voxelGrid, dt);

	// Simple Euler integration for updating the player's position.
	Double3 newPosition = this->camera.position + (this->velocity * dt);

	// Update the position if valid.
	if (std::isfinite(newPosition.length()))
	{
		this->camera.position = newPosition;
	}

	if (this->onGround(voxelGrid))
	{
		// Slow down the player's horizontal velocity with some friction.
		Double2 velocityXZ(this->velocity.x, this->velocity.z);
		Double2 frictionDirection = Double2(-velocityXZ.x, -velocityXZ.y).normalized();
		double frictionMagnitude = velocityXZ.length() * Player::FRICTION;

		if (std::isfinite(frictionDirection.length()) && (frictionMagnitude > EPSILON))
		{
			this->accelerate(Double3(frictionDirection.x, 0.0, frictionDirection.y),
				frictionMagnitude, true, dt);
		}
	}
}

void Player::tick(Game &game, double dt)
{
	// Update player position and velocity due to collisions.
	this->updatePhysics(game.getGameData().getVoxelGrid(), dt);

	// Tick weapon animation.
	this->weaponAnimation.tick(dt);
}
<commit_msg>Added lambda return type.<commit_after>#include <cassert>
#include <cmath>
#include <vector>

#include "Player.h"

#include "EntityType.h"
#include "GenderName.h"
#include "../Game/Game.h"
#include "../Game/GameData.h"
#include "../Items/WeaponType.h"
#include "../Math/Constants.h"
#include "../Utilities/String.h"
#include "../World/VoxelData.h"
#include "../World/VoxelGrid.h"

const double Player::HEIGHT = 0.70;
const double Player::STEPPING_HEIGHT = 0.25;
const double Player::JUMP_VELOCITY = 3.0;
const double Player::GRAVITY = 9.81;
const double Player::FRICTION = 4.0;

Player::Player(const std::string &displayName, GenderName gender, int raceID,
	const CharacterClass &charClass, int portraitID, const Double3 &position,
	const Double3 &direction, const Double3 &velocity, double maxWalkSpeed,
	double maxRunSpeed, WeaponType weaponType)
	: displayName(displayName), gender(gender), raceID(raceID), charClass(charClass),
	portraitID(portraitID), camera(position, direction), velocity(velocity),
	maxWalkSpeed(maxWalkSpeed), maxRunSpeed(maxRunSpeed), weaponAnimation(weaponType)
{
	assert(portraitID >= 0);
}

Player::~Player()
{

}

const Double3 &Player::getPosition() const
{
	return this->camera.position;
}

const std::string &Player::getDisplayName() const
{
	return this->displayName;
}

std::string Player::getFirstName() const
{
	std::vector<std::string> nameTokens = String::split(this->displayName);
	return nameTokens.at(0);
}

int Player::getPortraitID() const
{
	return this->portraitID;
}

GenderName Player::getGenderName() const
{
	return this->gender;
}

int Player::getRaceID() const
{
	return this->raceID;
}

const CharacterClass &Player::getCharacterClass() const
{
	return this->charClass;
}

const Double3 &Player::getDirection() const
{
	return this->camera.getDirection();
}

const Double3 &Player::getRight() const
{
	return this->camera.getRight();
}

Double2 Player::getGroundDirection() const
{
	const Double3 &direction = this->camera.getDirection();
	return Double2(direction.x, direction.z).normalized();
}

double Player::getJumpMagnitude() const
{
	return Player::JUMP_VELOCITY;
}

WeaponAnimation &Player::getWeaponAnimation()
{
	return this->weaponAnimation;
}

Int3 Player::getVoxelPosition() const
{
	return Int3(
		static_cast<int>(std::floor(this->camera.position.x)),
		static_cast<int>(std::floor(this->camera.position.y)),
		static_cast<int>(std::floor(this->camera.position.z)));
}

double Player::getFeetY() const
{
	return this->camera.position.y - Player::HEIGHT;
}

bool Player::onGround(const VoxelGrid &voxelGrid) const
{
	// To do: find a non-hack way to do this.

	return true;

	// This function seems kind of like a hack right now, since the player's feet
	// will frequently be at Y == 1.0, which is one voxel above the ground, and
	// it won't be considered as "on ground" unless it checks the voxel underneath
	// of this particular Y position (due to the rounding rules being used).
	/*const double feetY = this->getFeetY();
	const double feetVoxelYPos = std::floor(feetY);
	const bool closeEnoughToLowerVoxel = std::abs(feetY - feetVoxelYPos) < EPSILON;
	const Int3 feetVoxel(
		static_cast<int>(std::floor(this->camera.position.x)),
		static_cast<int>(feetVoxelYPos) - (closeEnoughToLowerVoxel ? 1 : 0),
		static_cast<int>(std::floor(this->camera.position.z)));

	const bool insideWorld = [&feetVoxel, &voxelGrid]()
	{
		return (feetVoxel.x >= 0) && (feetVoxel.x < voxelGrid.getWidth()) &&
			(feetVoxel.y >= 0) && (feetVoxel.y < voxelGrid.getHeight()) &&
			(feetVoxel.z >= 0) && (feetVoxel.z < voxelGrid.getDepth());
	}();

	// Don't try to dereference the voxel grid if the player's feet are outside.
	if (insideWorld)
	{
		const char feetVoxelID = voxelGrid.getVoxels()[feetVoxel.x +
			(feetVoxel.y * voxelGrid.getWidth()) +
			(feetVoxel.z * voxelGrid.getWidth() * voxelGrid.getHeight())];
		const VoxelData &voxelData = voxelGrid.getVoxelData(feetVoxelID);

		return (this->velocity.y == 0.0) && !voxelData.isAir() &&
			(feetY >= (feetVoxelYPos + voxelData.yOffset)) &&
			(feetY <= (feetVoxelYPos + voxelData.yOffset + voxelData.ySize));
	}
	else return false;*/
}

void Player::teleport(const Double3 &position)
{
	this->camera.position = position;
}

void Player::rotate(double dx, double dy, double hSensitivity, double vSensitivity)
{
	// Multiply sensitivities by 100 so the values in options.txt are nicer.
	this->camera.rotate(dx * (100.0 * hSensitivity), dy * (100.0 * vSensitivity));
}

void Player::lookAt(const Double3 &point)
{
	this->camera.lookAt(point);
}

void Player::handleCollision(const VoxelGrid &voxelGrid, double dt)
{
	auto getVoxel = [&voxelGrid](int x, int y, int z) -> VoxelData
	{
		// Voxels outside the world are air.
		if ((x < 0) || (x >= voxelGrid.getWidth()) ||
			(y < 0) || (y >= voxelGrid.getHeight()) ||
			(z < 0) || (z >= voxelGrid.getDepth()))
		{
			return VoxelData(0);
		}
		else
		{
			return voxelGrid.getVoxelData(voxelGrid.getVoxels()[x +
				(y * voxelGrid.getWidth()) +
				(z * voxelGrid.getWidth() * voxelGrid.getHeight())]);
		}
	};

	const double feetY = this->getFeetY();

	// Coordinates of the base of the voxel the feet are in.
	const double feetVoxelYPos = std::floor(feetY + (this->velocity.y * dt));

	// Get the voxel data for each voxel the player would touch on each axis.
	const Int3 playerVoxel = this->getVoxelPosition();
	const VoxelData &xVoxel = getVoxel(
		static_cast<int>(std::floor(this->camera.position.x + (this->velocity.x * dt))),
		playerVoxel.y,
		playerVoxel.z);
	const VoxelData &yVoxel = getVoxel(
		playerVoxel.x,
		static_cast<int>(feetVoxelYPos),
		playerVoxel.z);
	const VoxelData &zVoxel = getVoxel(
		playerVoxel.x,
		playerVoxel.y,
		static_cast<int>(std::floor(this->camera.position.z + (this->velocity.z * dt))));

	// Check horizontal collisions.

	// -- Temp hack until Y collision detection is implemented --
	auto isBridge = [](const VoxelData &voxel)
	{
		return (voxel.sideID == 42) && (voxel.floorID == 43) &&
			(voxel.ceilingID == 43);
	};

	if (!xVoxel.isAir() && !isBridge(xVoxel))
	{
		this->velocity.x = 0.0;
	}

	if (!zVoxel.isAir() && !isBridge(zVoxel))
	{
		this->velocity.z = 0.0;
	}
	// -- end hack --

	/*if (!xVoxel.isAir())
	{
		this->velocity.x = 0.0;
	}

	if (!zVoxel.isAir())
	{
		this->velocity.z = 0.0;
	}*/

	// To do: Y collision (snap Y position above ground if inside ground?).
	this->velocity.y = 0.0;

	// To do: use an axis-aligned bounding box or cylinder instead of a point?
}

void Player::accelerate(const Double3 &direction, double magnitude,
	bool isRunning, double dt)
{
	assert(dt >= 0.0);
	assert(magnitude >= 0.0);
	assert(std::isfinite(magnitude));
	assert(direction.isNormalized());

	// Simple Euler integration for updating velocity.
	Double3 newVelocity = this->velocity + (direction * (magnitude * dt));

	if (std::isfinite(newVelocity.length()))
	{
		this->velocity = newVelocity;
	}

	// Don't let the horizontal velocity be greater than the max speed for the
	// current movement state (i.e., walking/running).
	double maxSpeed = isRunning ? this->maxRunSpeed : this->maxWalkSpeed;
	Double2 velocityXZ(this->velocity.x, this->velocity.z);
	if (velocityXZ.length() > maxSpeed)
	{
		velocityXZ = velocityXZ.normalized() * maxSpeed;
	}

	// If the velocity is near zero, set it to zero. This fixes a problem where
	// the velocity could remain at a tiny magnitude and never reach zero.
	if (this->velocity.length() < 0.001)
	{
		this->velocity = Double3(0.0, 0.0, 0.0);
	}
}

void Player::accelerateInstant(const Double3 &direction, double magnitude)
{
	assert(direction.isNormalized());

	const Double3 additiveVelocity = direction * magnitude;

	if (std::isfinite(additiveVelocity.length()))
	{
		this->velocity = this->velocity + additiveVelocity;
	}
}

void Player::updatePhysics(const VoxelGrid &voxelGrid, double dt)
{
	// Acceleration from gravity (always).
	this->accelerate(-Double3::UnitY, Player::GRAVITY, false, dt);

	// Change the player's velocity based on collision.
	this->handleCollision(voxelGrid, dt);

	// Simple Euler integration for updating the player's position.
	Double3 newPosition = this->camera.position + (this->velocity * dt);

	// Update the position if valid.
	if (std::isfinite(newPosition.length()))
	{
		this->camera.position = newPosition;
	}

	if (this->onGround(voxelGrid))
	{
		// Slow down the player's horizontal velocity with some friction.
		Double2 velocityXZ(this->velocity.x, this->velocity.z);
		Double2 frictionDirection = Double2(-velocityXZ.x, -velocityXZ.y).normalized();
		double frictionMagnitude = velocityXZ.length() * Player::FRICTION;

		if (std::isfinite(frictionDirection.length()) && (frictionMagnitude > EPSILON))
		{
			this->accelerate(Double3(frictionDirection.x, 0.0, frictionDirection.y),
				frictionMagnitude, true, dt);
		}
	}
}

void Player::tick(Game &game, double dt)
{
	// Update player position and velocity due to collisions.
	this->updatePhysics(game.getGameData().getVoxelGrid(), dt);

	// Tick weapon animation.
	this->weaponAnimation.tick(dt);
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * 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 <iostream>
#include <vector>
#include <string>
#include <mapnik/util/fs.hpp>
#include <mapnik/quad_tree.hpp>
#include <mapnik/geometry_envelope.hpp>
#include "shapefile.hpp"
#include "shape_io.hpp"
#include "shape_index_featureset.hpp"
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#pragma GCC diagnostic pop

const int DEFAULT_DEPTH = 8;
const double DEFAULT_RATIO=0.55;

int main (int argc,char** argv)
{
    using namespace mapnik;
    namespace po = boost::program_options;

    bool verbose=false;
    bool index_parts = false;
    unsigned int depth = DEFAULT_DEPTH;
    double ratio = DEFAULT_RATIO;
    std::vector<std::string> shape_files;

    try
    {
        po::options_description desc("shapeindex utility");
        desc.add_options()
            ("help,h", "produce usage message")
            ("version,V","print version string")
            ("index-parts","index individual shape parts (default: no)")
            ("verbose,v","verbose output")
            ("depth,d", po::value<unsigned int>(), "max tree depth\n(default 8)")
            ("ratio,r",po::value<double>(),"split ratio (default 0.55)")
            ("shape_files",po::value<std::vector<std::string> >(),"shape files to index: file1 file2 ...fileN")
            ;

        po::positional_options_description p;
        p.add("shape_files",-1);
        po::variables_map vm;
        po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
        po::notify(vm);

        if (vm.count("version"))
        {
            std::clog << "version 0.3.0" <<std::endl;
            return 1;
        }

        if (vm.count("help"))
        {
            std::clog << desc << std::endl;
            return 1;
        }
        if (vm.count("verbose"))
        {
            verbose = true;
        }
        if (vm.count("index-parts"))
        {
            index_parts = true;
        }
        if (vm.count("depth"))
        {
            depth = vm["depth"].as<unsigned int>();
        }
        if (vm.count("ratio"))
        {
            ratio = vm["ratio"].as<double>();
        }

        if (vm.count("shape_files"))
        {
            shape_files=vm["shape_files"].as< std::vector<std::string> >();
        }
    }
    catch (std::exception const& ex)
    {
        std::clog << "Error: " << ex.what() << std::endl;
        return -1;
    }

    std::clog << "max tree depth:" << depth << std::endl;
    std::clog << "split ratio:" << ratio << std::endl;

    if (shape_files.size() == 0)
    {
        std::clog << "no shape files to index" << std::endl;
        return 0;
    }
    for (auto const& filename : shape_files)
    {
        std::clog << "processing " << filename << std::endl;
        std::string shapename (filename);
        boost::algorithm::ireplace_last(shapename,".shp","");
        std::string shapename_full (shapename + ".shp");
        std::string shxname(shapename + ".shx");
        if (! mapnik::util::exists (shapename_full))
        {
            std::clog << "Error : file " << shapename_full << " does not exist" << std::endl;
            continue;
        }
        if (! mapnik::util::exists(shxname))
        {
            std::clog << "Error : shapefile index file (*.shx) " << shxname << " does not exist" << std::endl;
            continue;
        }
        shape_file shp (shapename_full);

        if (! shp.is_open())
        {
            std::clog << "Error : cannot open " << shapename_full << std::endl;
            continue;
        }

        shape_file shx (shxname);
        if (!shx.is_open())
        {
            std::clog << "Error : cannot open " << shxname << std::endl;
            continue;
        }

        int code = shx.read_xdr_integer(); //file_code == 9994
        std::clog << code << std::endl;
        shx.skip(5*4);

        int file_length=shx.read_xdr_integer();
        int version=shx.read_ndr_integer();
        int shape_type=shx.read_ndr_integer();
        box2d<double> extent;
        shx.read_envelope(extent);

        std::clog << "length=" << file_length << std::endl;
        std::clog << "version=" << version << std::endl;
        std::clog << "type=" << shape_type << std::endl;
        std::clog << "extent:" << extent << std::endl;

        int pos = 50;
        shx.seek(pos * 2);
        mapnik::quad_tree<mapnik::detail::node> tree(extent, depth, ratio);
        int count = 0;

        if (shape_type != shape_io::shape_null)
        {
            while (shx.is_good() && pos <= file_length - 4)
            {
                int offset = shx.read_xdr_integer();
                int shx_content_length = shx.read_xdr_integer();
                pos += 4;
                box2d<double> item_ext;
                shp.seek(offset * 2);
                int record_number = shp.read_xdr_integer();
                int shp_content_length = shp.read_xdr_integer();
                if (shx_content_length != shp_content_length)
                {
                    std::clog << "Content length mismatch for record number " << record_number << std::endl;
                    continue;
                }
                shape_type = shp.read_ndr_integer();

                if (shape_type==shape_io::shape_point
                    || shape_type==shape_io::shape_pointm
                    || shape_type == shape_io::shape_pointz)
                {
                    double x=shp.read_double();
                    double y=shp.read_double();
                    item_ext=box2d<double>(x,y,x,y);
                }
                else if (index_parts &&
                         (shape_type == shape_io::shape_polygon || shape_type == shape_io::shape_polygonm || shape_type == shape_io::shape_polygonz
                          || shape_type == shape_io::shape_polyline || shape_type == shape_io::shape_polylinem || shape_type == shape_io::shape_polylinez))
                {
                    shp.read_envelope(item_ext);
                    int num_parts = shp.read_ndr_integer();
                    int num_points = shp.read_ndr_integer();
                    std::vector<int> parts;
                    parts.resize(num_parts);
                    std::for_each(parts.begin(), parts.end(), [&](int & part) { part = shp.read_ndr_integer();});
                    for (int k = 0; k < num_parts; ++k)
                    {
                        int start = parts[k];
                        int end;
                        if (k == num_parts - 1) end = num_points;
                        else end = parts[k + 1];

                        mapnik::geometry::linear_ring<double> ring;
                        ring.reserve(end - start);
                        for (int j = start; j < end; ++j)
                        {
                            double x = shp.read_double();
                            double y = shp.read_double();
                            ring.emplace_back(x, y);
                        }
                        item_ext = mapnik::geometry::envelope(ring);
                        if (item_ext.valid())
                        {
                            if (verbose)
                            {
                                std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
                            }
                            tree.insert(mapnik::detail::node(offset * 2, start, end),item_ext);
                            ++count;
                        }
                    }
                    item_ext = mapnik::box2d<double>(); //invalid
                }
                else
                {
                    shp.read_envelope(item_ext);
                }

                if (item_ext.valid())
                {
                    if (verbose)
                    {
                        std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
                    }
                    tree.insert(mapnik::detail::node(offset * 2,-1,0),item_ext);
                    ++count;
                }
            }
        }

        if (count > 0)
        {
            std::clog << " number shapes=" << count << std::endl;
            std::fstream file((shapename+".index").c_str(),
                              std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
            if (!file)
            {
                std::clog << "cannot open index file for writing file \""
                          << (shapename+".index") << "\"" << std::endl;
            }
            else
            {
                tree.trim();
                std::clog << " number nodes=" << tree.count() << std::endl;
                file.exceptions(std::ios::failbit | std::ios::badbit);
                tree.write(file);
                file.flush();
                file.close();
            }
        }
        else
        {
            std::clog << "No non-empty geometries in shapefile" << std::endl;
        }
    }

    std::clog << "done!" << std::endl;
    return 0;
}
<commit_msg>shapeindex - skip 'null' shapes (ref #3288)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * 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 <iostream>
#include <vector>
#include <string>
#include <mapnik/util/fs.hpp>
#include <mapnik/quad_tree.hpp>
#include <mapnik/geometry_envelope.hpp>
#include "shapefile.hpp"
#include "shape_io.hpp"
#include "shape_index_featureset.hpp"
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#pragma GCC diagnostic pop

const int DEFAULT_DEPTH = 8;
const double DEFAULT_RATIO=0.55;

int main (int argc,char** argv)
{
    using namespace mapnik;
    namespace po = boost::program_options;

    bool verbose=false;
    bool index_parts = false;
    unsigned int depth = DEFAULT_DEPTH;
    double ratio = DEFAULT_RATIO;
    std::vector<std::string> shape_files;

    try
    {
        po::options_description desc("shapeindex utility");
        desc.add_options()
            ("help,h", "produce usage message")
            ("version,V","print version string")
            ("index-parts","index individual shape parts (default: no)")
            ("verbose,v","verbose output")
            ("depth,d", po::value<unsigned int>(), "max tree depth\n(default 8)")
            ("ratio,r",po::value<double>(),"split ratio (default 0.55)")
            ("shape_files",po::value<std::vector<std::string> >(),"shape files to index: file1 file2 ...fileN")
            ;

        po::positional_options_description p;
        p.add("shape_files",-1);
        po::variables_map vm;
        po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
        po::notify(vm);

        if (vm.count("version"))
        {
            std::clog << "version 0.3.0" <<std::endl;
            return 1;
        }

        if (vm.count("help"))
        {
            std::clog << desc << std::endl;
            return 1;
        }
        if (vm.count("verbose"))
        {
            verbose = true;
        }
        if (vm.count("index-parts"))
        {
            index_parts = true;
        }
        if (vm.count("depth"))
        {
            depth = vm["depth"].as<unsigned int>();
        }
        if (vm.count("ratio"))
        {
            ratio = vm["ratio"].as<double>();
        }

        if (vm.count("shape_files"))
        {
            shape_files=vm["shape_files"].as< std::vector<std::string> >();
        }
    }
    catch (std::exception const& ex)
    {
        std::clog << "Error: " << ex.what() << std::endl;
        return -1;
    }

    std::clog << "max tree depth:" << depth << std::endl;
    std::clog << "split ratio:" << ratio << std::endl;

    if (shape_files.size() == 0)
    {
        std::clog << "no shape files to index" << std::endl;
        return 0;
    }
    for (auto const& filename : shape_files)
    {
        std::clog << "processing " << filename << std::endl;
        std::string shapename (filename);
        boost::algorithm::ireplace_last(shapename,".shp","");
        std::string shapename_full (shapename + ".shp");
        std::string shxname(shapename + ".shx");
        if (! mapnik::util::exists (shapename_full))
        {
            std::clog << "Error : file " << shapename_full << " does not exist" << std::endl;
            continue;
        }
        if (! mapnik::util::exists(shxname))
        {
            std::clog << "Error : shapefile index file (*.shx) " << shxname << " does not exist" << std::endl;
            continue;
        }
        shape_file shp (shapename_full);

        if (! shp.is_open())
        {
            std::clog << "Error : cannot open " << shapename_full << std::endl;
            continue;
        }

        shape_file shx (shxname);
        if (!shx.is_open())
        {
            std::clog << "Error : cannot open " << shxname << std::endl;
            continue;
        }

        int code = shx.read_xdr_integer(); //file_code == 9994
        std::clog << code << std::endl;
        shx.skip(5*4);

        int file_length=shx.read_xdr_integer();
        int version=shx.read_ndr_integer();
        int shape_type=shx.read_ndr_integer();
        box2d<double> extent;
        shx.read_envelope(extent);

        std::clog << "length=" << file_length << std::endl;
        std::clog << "version=" << version << std::endl;
        std::clog << "type=" << shape_type << std::endl;
        std::clog << "extent:" << extent << std::endl;

        int pos = 50;
        shx.seek(pos * 2);
        mapnik::quad_tree<mapnik::detail::node> tree(extent, depth, ratio);
        int count = 0;

        if (shape_type != shape_io::shape_null)
        {
            while (shx.is_good() && pos <= file_length - 4)
            {
                int offset = shx.read_xdr_integer();
                int shx_content_length = shx.read_xdr_integer();
                pos += 4;
                box2d<double> item_ext;
                shp.seek(offset * 2);
                int record_number = shp.read_xdr_integer();
                int shp_content_length = shp.read_xdr_integer();
                if (shx_content_length != shp_content_length)
                {
                    std::clog << "Content length mismatch for record number " << record_number << std::endl;
                    continue;
                }
                shape_type = shp.read_ndr_integer();

                if (shape_type == shape_io::shape_null) continue;

                if (shape_type==shape_io::shape_point
                    || shape_type==shape_io::shape_pointm
                    || shape_type == shape_io::shape_pointz)
                {
                    double x=shp.read_double();
                    double y=shp.read_double();
                    item_ext=box2d<double>(x,y,x,y);
                }
                else if (index_parts &&
                         (shape_type == shape_io::shape_polygon || shape_type == shape_io::shape_polygonm || shape_type == shape_io::shape_polygonz
                          || shape_type == shape_io::shape_polyline || shape_type == shape_io::shape_polylinem || shape_type == shape_io::shape_polylinez))
                {
                    shp.read_envelope(item_ext);
                    int num_parts = shp.read_ndr_integer();
                    int num_points = shp.read_ndr_integer();
                    std::vector<int> parts;
                    parts.resize(num_parts);
                    std::for_each(parts.begin(), parts.end(), [&](int & part) { part = shp.read_ndr_integer();});
                    for (int k = 0; k < num_parts; ++k)
                    {
                        int start = parts[k];
                        int end;
                        if (k == num_parts - 1) end = num_points;
                        else end = parts[k + 1];

                        mapnik::geometry::linear_ring<double> ring;
                        ring.reserve(end - start);
                        for (int j = start; j < end; ++j)
                        {
                            double x = shp.read_double();
                            double y = shp.read_double();
                            ring.emplace_back(x, y);
                        }
                        item_ext = mapnik::geometry::envelope(ring);
                        if (item_ext.valid())
                        {
                            if (verbose)
                            {
                                std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
                            }
                            tree.insert(mapnik::detail::node(offset * 2, start, end),item_ext);
                            ++count;
                        }
                    }
                    item_ext = mapnik::box2d<double>(); //invalid
                }
                else
                {
                    shp.read_envelope(item_ext);
                }

                if (item_ext.valid())
                {
                    if (verbose)
                    {
                        std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
                    }
                    tree.insert(mapnik::detail::node(offset * 2,-1,0),item_ext);
                    ++count;
                }
            }
        }

        if (count > 0)
        {
            std::clog << " number shapes=" << count << std::endl;
            std::fstream file((shapename+".index").c_str(),
                              std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
            if (!file)
            {
                std::clog << "cannot open index file for writing file \""
                          << (shapename+".index") << "\"" << std::endl;
            }
            else
            {
                tree.trim();
                std::clog << " number nodes=" << tree.count() << std::endl;
                file.exceptions(std::ios::failbit | std::ios::badbit);
                tree.write(file);
                file.flush();
                file.close();
            }
        }
        else
        {
            std::clog << "No non-empty geometries in shapefile" << std::endl;
        }
    }

    std::clog << "done!" << std::endl;
    return 0;
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2018, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "PoolSQLCache.h"
#include "Nebula.h"

unsigned int PoolSQLCache::MAX_ELEMENTS = 10000;

PoolSQLCache::PoolSQLCache()
{
    pthread_mutex_init(&mutex, 0);
};

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void PoolSQLCache::lock_line(int oid)
{
    std::map<int, CacheLine *>::iterator it;

    CacheLine * cl;

    lock();

    it = cache.find(oid);

    if ( it == cache.end() )
    {
        cl = new CacheLine(0);

        cl->active++;

        cache.insert(make_pair(oid, cl));

        unlock();

        cl->lock();

        return;
    }

    cl = it->second;

    cl->active++;

    unlock();

    cl->lock();

    if ( cl->object != 0 )
    {
        cl->object->lock();

        delete cl->object;
    }

    cl->object = 0;

    return;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolSQLCache::set_line(int oid, PoolObjectSQL * object)
{
    std::map<int, CacheLine *>::iterator it;

    lock();

    it = cache.find(oid);

    if ( it == cache.end() )
    {
        unlock();

        return -1;
    }

    it->second->active--;

    it->second->object = object;

    it->second->unlock();

    if ( cache.size() > MAX_ELEMENTS )
    {
        flush_cache_lines();
    }

    unlock();

    return 0;
};

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void PoolSQLCache::flush_cache_lines()
{
    for (std::map<int,CacheLine *>::iterator it=cache.begin(); it!=cache.end();)
    {
        CacheLine * cl = it->second;

        int rc = cl->trylock();

        if ( rc == EBUSY ) // cache line locked
        {
            ++it;
            continue;
        }

        if ( cl->active > 0 ) // cache line being set
        {
            cl->unlock();

            ++it;
            continue;
        }

        if ( cl->object != 0 )
        {
            rc =  cl->object->trylock();

            if ( rc == EBUSY ) //object int use
            {
                cl->unlock();

                ++it;
                continue;
            }
        }

        delete it->second; // cache line & pool object locked & active == 0

        it = cache.erase(it);
    }
};

<commit_msg>Prevent race conditions when getting elements for the first time or after flushing the cache<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2018, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "PoolSQLCache.h"
#include "Nebula.h"

unsigned int PoolSQLCache::MAX_ELEMENTS = 10000;

PoolSQLCache::PoolSQLCache()
{
    pthread_mutex_init(&mutex, 0);
};

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void PoolSQLCache::lock_line(int oid)
{
    std::map<int, CacheLine *>::iterator it;

    CacheLine * cl;

    lock();

    it = cache.find(oid);

    if ( it == cache.end() )
    {
        cl = new CacheLine(0);

        cache.insert(make_pair(oid, cl));
    }
    else
    {
        cl = it->second;
    }

    cl->active++;

    unlock();

    cl->lock();

    if ( cl->object != 0 )
    {
        cl->object->lock();

        delete cl->object;

        cl->object = 0;
    }

    return;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int PoolSQLCache::set_line(int oid, PoolObjectSQL * object)
{
    std::map<int, CacheLine *>::iterator it;

    lock();

    it = cache.find(oid);

    if ( it == cache.end() )
    {
        unlock();

        return -1;
    }

    it->second->active--;

    it->second->object = object;

    it->second->unlock();

    if ( cache.size() > MAX_ELEMENTS )
    {
        flush_cache_lines();
    }

    unlock();

    return 0;
};

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void PoolSQLCache::flush_cache_lines()
{
    for (std::map<int,CacheLine *>::iterator it=cache.begin(); it!=cache.end();)
    {
        CacheLine * cl = it->second;

        int rc = cl->trylock();

        if ( rc == EBUSY ) // cache line locked
        {
            ++it;
            continue;
        }

        if ( cl->active > 0 ) // cache line being set
        {
            cl->unlock();

            ++it;
            continue;
        }

        if ( cl->object != 0 )
        {
            rc =  cl->object->trylock();

            if ( rc == EBUSY ) //object int use
            {
                cl->unlock();

                ++it;
                continue;
            }
        }

        delete it->second; // cache line & pool object locked & active == 0

        it = cache.erase(it);
    }
};

<|endoftext|>


<commit_before>#include <stdio.h>
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream
#include <cstdlib>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <sys/types.h>
#include <dirent.h>
#include <cstdarg>
#include "omp.h"

using namespace std;

int const NUM_ROWS = 6;
int const NUM_COLS = 16;
int p[NUM_ROWS*NUM_COLS];
string station;

inline std::string format(const char* fmt, ...){
    int size = 512;
    char* buffer = 0;
    buffer = new char[size];
    va_list vl;
    va_start(vl, fmt);
    int nsize = vsnprintf(buffer, size, fmt, vl);
    if(size<=nsize){ //fail delete buffer and try again
        delete[] buffer;
        buffer = 0;
        buffer = new char[nsize+1]; //+1 for /0
        nsize = vsnprintf(buffer, size, fmt, vl);
    }
    std::string ret(buffer);
    va_end(vl);
    delete[] buffer;
    return ret;
}

void printLines(int *arr){
	// OPTIONAL: print out the results
	// #pragma parallel for
	for (int j = 0; j < NUM_ROWS; j++) {
		for (int k = 0; k < NUM_COLS; k++){
			printf("%d ", arr[j * NUM_COLS + k] );
		}
		printf("\n");
	}
}

// windrose pseudocode

// Divide speed into 6 buckets
// Negative speeds are not allowed
int speedBucket(float data) {
	if (data < 0) return -1;

	// Stratified divide
	if (data < 1) {
		return 0;
	} else if (data < 3) {
		return 1;
	} else if (data < 5) {
		return 2;
	} else if (data < 7) {
		return 3;
	} else if (data < 9) {
		return 4;
	}else {
		return 5;
	}
}

// Divide 360 into 16 sectors
int directionBucket(float degrees) {
	int bucket = degrees / 22.5 ;
	return bucket;
}

void allocate(){
    memset(p, 0, sizeof(p));
}

void check(char *argv[],int argc){
    std::string help ("-h");
    if (argc != 4 || help.compare(argv[1]) == 0 ) {
        printf("USAGE: ./windrose datafiledirectory stationId HH00\n");
        printf("Enter 0 for null values\n");
        //return 0;
    }
    station = argv[2];
}

void calc(char *argv[],int argc){

    #pragma omp parallel for
    for (int i = 2; i<= 14; i++) {
        std::string filename  = format("./%smesonet-20%02d0621_%s.dat", argv[1], i, argv[3]);
        printf("%s\n", filename.c_str());

        // Cache line is 64 bytes - approx 2 lines

        ifstream datafile(filename.c_str(), ios::ate | ios::binary);
        long datasize = datafile.tellg();
        datafile.seekg(0);
        vector<unsigned char> bytes(datasize, 0);
        datafile.read((char*)&bytes[0], bytes.size());

        for (int j = 0; j < datasize; j+=(5+4*sizeof(int)))
        {
            int spd, dir, lat, lon;

            // 5 bytes station id
            // string stationid = string(1, bytes[j]);
            string stationid (reinterpret_cast<char const*>(&bytes[j]), 5);

            if (stationid == station) {
                // Intel CPU is little endian
                spd = (bytes[j+5]<<24)|(bytes[j+6]<<16)|(bytes[j+7]<<8)|(bytes[j+8]);
                dir = (bytes[j+9]<<24)|(bytes[j+10]<<16)|(bytes[j+11]<<8)|(bytes[j+12]);
                // printf("%s %d %d %d %d\n", stationid.c_str(), spd, dir, j+5, j+5+sizeof(int));

                int spdbckt = speedBucket(spd/100.);
                int dirbckt = directionBucket(dir/100.);

                #pragma omp critical
                {
                    p[spdbckt* NUM_COLS + dirbckt]++;
                }
            }
        }
    }
}

// Main - load files and
int main(int argc, char *argv[]){

    allocate();
	// Scrub input
    check(argv,argc);

    calc(argv,argc);

	printLines(p);
  	return 0;
}

int dirNumFiles(char *directory)
{
	DIR *dp;
	int i;
 	struct dirent *ep;
  	dp = opendir ("./");

  	if (dp != NULL)
  	{
    	while (ep = readdir (dp))
      	i++;

    	(void) closedir (dp);
  	}
  	else
    	perror ("Couldn't open the directory");

  	printf("There's %d files in the current directory.\n", i);
  	return i;
}<commit_msg>code change for swig implementation<commit_after>#include <stdio.h>
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream
#include <cstdlib>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <sys/types.h>
#include <dirent.h>
#include <cstdarg>
#include "omp.h"

using namespace std;

int const NUM_ROWS = 6;
int const NUM_COLS = 16;
int p[NUM_ROWS*NUM_COLS];
string station;
//std::string argval[];
//std::string argval2;

inline std::string format(const char* fmt, ...){
    int size = 512;
    char* buffer = 0;
    buffer = new char[size];
    va_list vl;
    va_start(vl, fmt);
    int nsize = vsnprintf(buffer, size, fmt, vl);
    if(size<=nsize){ //fail delete buffer and try again
        delete[] buffer;
        buffer = 0;
        buffer = new char[nsize+1]; //+1 for /0
        nsize = vsnprintf(buffer, size, fmt, vl);
    }
    std::string ret(buffer);
    va_end(vl);
    delete[] buffer;
    return ret;
}

void printLines(){
	// OPTIONAL: print out the results
	// #pragma parallel for
	for (int j = 0; j < NUM_ROWS; j++) {
		for (int k = 0; k < NUM_COLS; k++){
			printf("%d ", p[j * NUM_COLS + k] );
		}
		printf("\n");
	}
}

// windrose pseudocode

// Divide speed into 6 buckets
// Negative speeds are not allowed
int speedBucket(float data) {
	if (data < 0) return -1;

	// Stratified divide
	if (data < 1) {
		return 0;
	} else if (data < 3) {
		return 1;
	} else if (data < 5) {
		return 2;
	} else if (data < 7) {
		return 3;
	} else if (data < 9) {
		return 4;
	}else {
		return 5;
	}
}

// Divide 360 into 16 sectors
int directionBucket(float degrees) {
	int bucket = degrees / 22.5 ;
	return bucket;
}

void allocate(){
    memset(p, 0, sizeof(p));
}

void check(char *argv1, char *argv2, int argc){
    std::string help ("-h");
    if (argc != 4 || help.compare(argv1) == 0 ) {
        printf("USAGE: ./windrose datafiledirectory stationId HH00\n");
        printf("Enter 0 for null values\n");
        //return 0;
    }
    station = argv2;
}

void calc(char *argv1, char *argv3,int argc){

    #pragma omp parallel for
    for (int i = 2; i<= 14; i++) {
        std::string filename  = format("./%smesonet-20%02d0621_%s.dat", argv1, i, argv3);
        printf("%s\n", filename.c_str());

        // Cache line is 64 bytes - approx 2 lines

        ifstream datafile(filename.c_str(), ios::ate | ios::binary);
        long datasize = datafile.tellg();
        datafile.seekg(0);
        vector<unsigned char> bytes(datasize, 0);
        datafile.read((char*)&bytes[0], bytes.size());

        for (int j = 0; j < datasize; j+=(5+4*sizeof(int)))
        {
            int spd, dir, lat, lon;

            // 5 bytes station id
            // string stationid = string(1, bytes[j]);
            string stationid (reinterpret_cast<char const*>(&bytes[j]), 5);

            if (stationid == station) {
                // Intel CPU is little endian
                spd = (bytes[j+5]<<24)|(bytes[j+6]<<16)|(bytes[j+7]<<8)|(bytes[j+8]);
                dir = (bytes[j+9]<<24)|(bytes[j+10]<<16)|(bytes[j+11]<<8)|(bytes[j+12]);
                // printf("%s %d %d %d %d\n", stationid.c_str(), spd, dir, j+5, j+5+sizeof(int));

                int spdbckt = speedBucket(spd/100.);
                int dirbckt = directionBucket(dir/100.);

                #pragma omp critical
                {
                    p[spdbckt* NUM_COLS + dirbckt]++;
                }
            }
        }
    }
}

// Main - load files and
int main(int argc, char *argv[]){

    allocate();
	// Scrub input
  //  argval1(argv[1]);
    //argval2(argv[2]);

    //for(int i=0;i<argc;i++){
      //  argval[i](argv[i]);
    //}

    check(argv[1],argv[2],argc);

    calc(argv[1],argv[3],argc);

	printLines();
  	return 0;
}

int dirNumFiles(char *directory)
{
	DIR *dp;
	int i;
 	struct dirent *ep;
  	dp = opendir ("./");

  	if (dp != NULL)
  	{
    	while (ep = readdir (dp))
      	i++;

    	(void) closedir (dp);
  	}
  	else
    	perror ("Couldn't open the directory");

  	printf("There's %d files in the current directory.\n", i);
  	return i;
}<|endoftext|>


<commit_before>/* RTcmix - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <RTcmixMIDI.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <assert.h>

// if INBUF_SIZE is 0, PortMidi uses a default value
#define INBUF_SIZE		0
#define MSG_QUEUE_SIZE	32

enum {
	kQuitMsg = 0
};

RTcmixMIDI::RTcmixMIDI()
	: _instream(NULL), _outstream(NULL), _active(false)
{
	_MIDIToMain = Pm_QueueCreate(MSG_QUEUE_SIZE, sizeof(long));
	_mainToMIDI = Pm_QueueCreate(MSG_QUEUE_SIZE, sizeof(long));
//FIXME: how to handle error?
	if (_mainToMIDI == NULL || _MIDIToMain == NULL) {
		fprintf(stderr, "Could not create MIDI message queues.\n");
		return;
	}

	clear();
}

RTcmixMIDI::~RTcmixMIDI()
{
	long msg = kQuitMsg;
	Pm_Enqueue(_mainToMIDI, &msg);

	// wait for acknowlegement
	int spin;
	do {
		spin = Pm_Dequeue(_MIDIToMain, &msg);
	} while (spin == 0);

	Pt_Stop();	// stop timer
	if (_instream)
		Pm_Close(_instream);
	if (_outstream)
		Pm_Close(_outstream);

	Pm_QueueDestroy(_mainToMIDI);
	Pm_QueueDestroy(_MIDIToMain);

	Pm_Terminate();
}

int RTcmixMIDI::init()
{
	// Start the timer before starting MIDI I/O.  The timer runs the callback
	// function every SLEEP_MSEC milliseconds.
	Pt_Start(SLEEP_MSEC, &_processMIDI, this);

	Pm_Initialize();

//FIXME: read device name from Option class?
	int id = Pm_GetDefaultInputDeviceID();
	const PmDeviceInfo *info = Pm_GetDeviceInfo(id);
	if (info == NULL) {
		fprintf(stderr, "Could not open input device %d.\n", id);
		return -1;
	}

	PmError err = Pm_OpenInput(&_instream, id, NULL, INBUF_SIZE, NULL, NULL);
	if (err != pmNoError) {
		fprintf(stderr, "Could not open input stream: %s.\n",
									Pm_GetErrorText(err));
		return -1;
	}

	Pm_SetFilter(_instream, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX);

	// Empty buffer after setting filter, in case anything got through before.
	PmEvent buffer;
	while (Pm_Poll(_instream))
		Pm_Read(_instream, &buffer, 1);

	// enable processing in MIDI thread (_processMIDI)
	active(true);

	return 0;
}

void RTcmixMIDI::clear()
{
	for (int chan = 0; chan < 16; chan++) {
		_bend[chan] = -INT_MAX;
		_program[chan] = -INT_MAX;
		_chanpress[chan] = -INT_MAX;
		for (int i = 0; i < 128; i++) {
			_noteonvel[chan][i] = -INT_MAX;
			_noteoffvel[chan][i] = -INT_MAX;
			_control[chan][i] = -INT_MAX;
			_polypress[chan][i] = -INT_MAX;
		}
	}
}

// -------------------------------------------------------------------- dump ---
// Just for debugging.

const char *RTcmixMIDI::getValueString(const int val)
{
	if (val == -INT_MAX)
		return "--";

	static char buf[16];
	snprintf(buf, 16, "%d", val);
	return buf;
}

void RTcmixMIDI::dump()
{
	printf("\nDumping current MIDI state...\n");
	for (int chan = 0; chan < 16; chan++) {
		printf("---------------------------------------- Channel %d\n", chan + 1);
		printf("   Bend:\t%s\n", getValueString(_bend[chan]));
		printf("   Program:\t%s\n", getValueString(_program[chan]));
		printf("   ChanPress:\t%s\n", getValueString(_chanpress[chan]));
		printf("   NoteOnVel:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_noteonvel[chan][i]));
		printf("   NoteOffVel:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_noteoffvel[chan][i]));
		printf("   Control:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_control[chan][i]));
		printf("   PolyPress:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_polypress[chan][i]));
		printf("\n");
	}
}

// ------------------------------------------------------------ _processMIDI ---

enum {
	kNoteOff = 0x80,
	kNoteOn = 0x90,
	kPolyPress = 0xA0,
	kControl = 0xB0,
	kProgram = 0xC0,
	kChanPress = 0xD0,
	kPitchBend = 0xE0
} StatusByte;

// This is called from the MIDI worker thread.  The RTcmixMIDI object, held by
// main thread, communicates with this worker thread by passing messages
// back and forth.
void RTcmixMIDI::_processMIDI(PtTimestamp timestamp, void *context)
{
	RTcmixMIDI *obj = (RTcmixMIDI *) context;

	// Check for messages from object.
	PmError result;
	do {
		long msg;
		result = Pm_Dequeue(obj->mainToMIDI(), &msg);
		if (result) {
			if (msg == kQuitMsg) {
				// acknowledge receipt of quit message
				Pm_Enqueue(obj->MIDIToMain(), &msg);
				obj->active(false);
				return;
			}
		}
	} while (result);

	// Don't poll MIDI until initialization completes.  We still listen for
	// messages, in case RTcmixMIDI::init fails and dtor then called.
	if (!obj->active())
		return;

	// See if there is any midi input to process.
	do {
		result = Pm_Poll(obj->instream());
		if (result) {
			long status, chan, data1, data2;
			PmEvent buffer;

			if (Pm_Read(obj->instream(), &buffer, 1) == pmBufferOverflow)
				continue;

			// unless there was overflow, we should have a message now
			status = Pm_MessageStatus(buffer.message);
			data1 = Pm_MessageData1(buffer.message);
			data2 = Pm_MessageData2(buffer.message);

			chan = status & 0x0F;

			switch (status & 0xF0) {
				case kNoteOn:
					obj->setNoteOnVel(chan, data1, data2);
					break;
				case kNoteOff:
					obj->setNoteOffVel(chan, data1, data2);
					break;
				case kPolyPress:
					obj->setPolyPress(chan, data1, data2);
					break;
				case kControl:
					obj->setControl(chan, data1, data2);
					break;
				case kProgram:
					obj->setProgram(chan, data1);
					break;
				case kChanPress:
					obj->setChanPress(chan, data1);
					break;
				case kPitchBend:
					obj->setBend(chan, ((data2 << 7) + data1) - 8192);
					break;
				default:
					printf("0x%.2x, %ld, %ld\n", (u_char) status, data1, data2);
					break;
			}
		}
	} while (result);

//sleep(2); obj->dump();
}

RTcmixMIDI *createMIDIPort()
{
	RTcmixMIDI *midiport = new RTcmixMIDI();
	if (midiport) {
		if (midiport->init() == -1) {
			delete midiport;
			return NULL;
		}
	}

	return midiport;
}

<commit_msg>Get device name from prefs; move msg queue creation to init; err msg changes.<commit_after>/* RTcmix - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <RTcmixMIDI.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <Option.h>

// if INBUF_SIZE is 0, PortMidi uses a default value
#define INBUF_SIZE		0
#define MSG_QUEUE_SIZE	32

enum {
	kQuitMsg = 0
};

RTcmixMIDI::RTcmixMIDI()
	: _instream(NULL), _outstream(NULL), _active(false)
{
	clear();
}

RTcmixMIDI::~RTcmixMIDI()
{
	long msg = kQuitMsg;
	Pm_Enqueue(_mainToMIDI, &msg);

	// wait for acknowlegement
	int spin;
	do {
		spin = Pm_Dequeue(_MIDIToMain, &msg);
	} while (spin == 0);

	Pt_Stop();	// stop timer
	if (_instream)
		Pm_Close(_instream);
	if (_outstream)
		Pm_Close(_outstream);

	Pm_QueueDestroy(_mainToMIDI);
	Pm_QueueDestroy(_MIDIToMain);

	Pm_Terminate();
}

int RTcmixMIDI::init()
{
	_MIDIToMain = Pm_QueueCreate(MSG_QUEUE_SIZE, sizeof(long));
	_mainToMIDI = Pm_QueueCreate(MSG_QUEUE_SIZE, sizeof(long));
	if (_mainToMIDI == NULL || _MIDIToMain == NULL) {
		fprintf(stderr, "Could not create MIDI message queues.\n");
		return -1;
	}

	// Start the timer before starting MIDI I/O.  The timer runs the callback
	// function every SLEEP_MSEC milliseconds.
	Pt_Start(SLEEP_MSEC, &_processMIDI, this);

	Pm_Initialize();

	int id = 0;
	const char *devname = Option::midiInDevice();
	if (devname) {
		const int numdev = Pm_CountDevices();
		for ( ; id < numdev; id++) {
			const PmDeviceInfo *info = Pm_GetDeviceInfo(id);
			if (info->input) {
				if (strcmp(info->name, devname) == 0)
					break;
			}
		}
		if (id == 0 || id == numdev) {
			fprintf(stderr, "WARNING: no match for MIDI input device \"%s\""
							" ... using default.\n", devname);
			id = Pm_GetDefaultInputDeviceID();
		}
	}
	else {
		fprintf(stderr, "WARNING: using default MIDI input device.\n");
		id = Pm_GetDefaultInputDeviceID();
	}
	const PmDeviceInfo *info = Pm_GetDeviceInfo(id);
	if (info == NULL) {
		fprintf(stderr, "Could not open MIDI input device %d.\n", id);
		return -1;
	}

	PmError err = Pm_OpenInput(&_instream, id, NULL, INBUF_SIZE, NULL, NULL);
	if (err != pmNoError) {
		fprintf(stderr, "Could not open MIDI input stream: %s.\n",
									Pm_GetErrorText(err));
		return -1;
	}

	Pm_SetFilter(_instream, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX);

	// Empty buffer after setting filter, in case anything got through before.
	PmEvent buffer;
	while (Pm_Poll(_instream))
		Pm_Read(_instream, &buffer, 1);

	// enable processing in MIDI thread (_processMIDI)
	active(true);

	return 0;
}

void RTcmixMIDI::clear()
{
	for (int chan = 0; chan < 16; chan++) {
		_bend[chan] = -INT_MAX;
		_program[chan] = -INT_MAX;
		_chanpress[chan] = -INT_MAX;
		for (int i = 0; i < 128; i++) {
			_noteonvel[chan][i] = -INT_MAX;
			_noteoffvel[chan][i] = -INT_MAX;
			_control[chan][i] = -INT_MAX;
			_polypress[chan][i] = -INT_MAX;
		}
	}
}

// -------------------------------------------------------------------- dump ---
// Just for debugging.

const char *RTcmixMIDI::getValueString(const int val)
{
	if (val == -INT_MAX)
		return "--";

	static char buf[16];
	snprintf(buf, 16, "%d", val);
	return buf;
}

void RTcmixMIDI::dump()
{
	printf("\nDumping current MIDI state...\n");
	for (int chan = 0; chan < 16; chan++) {
		printf("---------------------------------------- Channel %d\n", chan + 1);
		printf("   Bend:\t%s\n", getValueString(_bend[chan]));
		printf("   Program:\t%s\n", getValueString(_program[chan]));
		printf("   ChanPress:\t%s\n", getValueString(_chanpress[chan]));
		printf("   NoteOnVel:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_noteonvel[chan][i]));
		printf("   NoteOffVel:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_noteoffvel[chan][i]));
		printf("   Control:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_control[chan][i]));
		printf("   PolyPress:\n");
		for (int i = 0; i < 128; i++)
			printf("      [%d]:\t%s\n", i, getValueString(_polypress[chan][i]));
		printf("\n");
	}
}

// ------------------------------------------------------------ _processMIDI ---

enum {
	kNoteOff = 0x80,
	kNoteOn = 0x90,
	kPolyPress = 0xA0,
	kControl = 0xB0,
	kProgram = 0xC0,
	kChanPress = 0xD0,
	kPitchBend = 0xE0
} StatusByte;

// This is called from the MIDI worker thread.  The RTcmixMIDI object, held by
// main thread, communicates with this worker thread by passing messages
// back and forth.
void RTcmixMIDI::_processMIDI(PtTimestamp timestamp, void *context)
{
	RTcmixMIDI *obj = (RTcmixMIDI *) context;

	// Check for messages from object.
	PmError result;
	do {
		long msg;
		result = Pm_Dequeue(obj->mainToMIDI(), &msg);
		if (result) {
			if (msg == kQuitMsg) {
				// acknowledge receipt of quit message
				Pm_Enqueue(obj->MIDIToMain(), &msg);
				obj->active(false);
				return;
			}
		}
	} while (result);

	// Don't poll MIDI until initialization completes.  We still listen for
	// messages, in case RTcmixMIDI::init fails and dtor then called.
	if (!obj->active())
		return;

	// See if there is any midi input to process.
	do {
		result = Pm_Poll(obj->instream());
		if (result) {
			long status, chan, data1, data2;
			PmEvent buffer;

			if (Pm_Read(obj->instream(), &buffer, 1) == pmBufferOverflow)
				continue;

			// unless there was overflow, we should have a message now
			status = Pm_MessageStatus(buffer.message);
			data1 = Pm_MessageData1(buffer.message);
			data2 = Pm_MessageData2(buffer.message);

			chan = status & 0x0F;

			switch (status & 0xF0) {
				case kNoteOn:
					obj->setNoteOnVel(chan, data1, data2);
					break;
				case kNoteOff:
					obj->setNoteOffVel(chan, data1, data2);
					break;
				case kPolyPress:
					obj->setPolyPress(chan, data1, data2);
					break;
				case kControl:
					obj->setControl(chan, data1, data2);
					break;
				case kProgram:
					obj->setProgram(chan, data1);
					break;
				case kChanPress:
					obj->setChanPress(chan, data1);
					break;
				case kPitchBend:
					obj->setBend(chan, ((data2 << 7) + data1) - 8192);
					break;
				default:
					printf("0x%.2x, %ld, %ld\n", (u_char) status, data1, data2);
					break;
			}
		}
	} while (result);

//sleep(2); obj->dump();
}

RTcmixMIDI *createMIDIPort()
{
	RTcmixMIDI *midiport = new RTcmixMIDI();
	if (midiport) {
		if (midiport->init() == -1) {
			delete midiport;
			return NULL;
		}
	}

	return midiport;
}

<|endoftext|>


<commit_before>#include "FilteredVolumeParamSet.h"

#include "Rendering/Volume.h"

#include "GPGPU/VolumeToVolumeFilter.h"

#include <cassert>
#include <iostream>

namespace NQVTK
{
	// ------------------------------------------------------------------------
	FilteredVolumeParamSet::FilteredVolumeParamSet(
		Volume *volume, GPGPU::VolumeToVolumeFilter *filter)
		: VolumeParamSet(0), originalVolume(0),
		filter(filter), filterEnabled(true)
	{
		assert(volume);
		assert(filter);

		// NOTE: don't subclass and make SetVolume virtual again!
		SetVolume(volume);

		SetFilterEnabled(false);
	}

	// ------------------------------------------------------------------------
	FilteredVolumeParamSet::~FilteredVolumeParamSet()
	{
		delete originalVolume;
		delete filter;
	}

	// ------------------------------------------------------------------------
	Volume *FilteredVolumeParamSet::SetVolume(Volume *volume)
	{
		Volume *old = originalVolume;
		// Don't return an old volume if it's not actually replaced
		if (originalVolume == volume) old = 0;

		originalVolume = volume;

		if (filterEnabled)
		{
			// Get rid of the filtered volume
			delete this->volume;
			this->volume = 0;
		}

		if (filter)
		{
			// Setup the filter
			bool res = filter->Setup(volume);
			if (!res)
			{
				std::cerr << "Error setting up filter" << std::endl;
				delete filter;
				filter = 0;
			}
		}

		return old;
	}

	// ------------------------------------------------------------------------
	void FilteredVolumeParamSet::SetFilterEnabled(bool enabled)
	{
		if (enabled == filterEnabled) return;

		if (!filter) return;

		filterEnabled = enabled;

		if (enabled)
		{
			// Turn on filtering
			volume = 0;
			Update();
		}
		else
		{
			// Delete filtered volume
			delete volume;
			volume = originalVolume;
		}
	}

	// ------------------------------------------------------------------------
	void FilteredVolumeParamSet::Update()
	{
		if (filterEnabled)
		{
			filter->scale = scale;
			volume = filter->Execute(volume);
		}
	}
}
<commit_msg>Fixed a crash when the filter can't be created.<commit_after>#include "FilteredVolumeParamSet.h"

#include "Rendering/Volume.h"

#include "GPGPU/VolumeToVolumeFilter.h"

#include <cassert>
#include <iostream>

namespace NQVTK
{
	// ------------------------------------------------------------------------
	FilteredVolumeParamSet::FilteredVolumeParamSet(
		Volume *volume, GPGPU::VolumeToVolumeFilter *filter)
		: VolumeParamSet(0), originalVolume(0),
		filter(filter), filterEnabled(true)
	{
		assert(volume);
		assert(filter);

		// NOTE: don't subclass and make SetVolume virtual again!
		SetVolume(volume);

		SetFilterEnabled(false);
	}

	// ------------------------------------------------------------------------
	FilteredVolumeParamSet::~FilteredVolumeParamSet()
	{
		delete originalVolume;
		delete filter;
	}

	// ------------------------------------------------------------------------
	Volume *FilteredVolumeParamSet::SetVolume(Volume *volume)
	{
		Volume *old = originalVolume;
		// Don't return an old volume if it's not actually replaced
		if (originalVolume == volume) old = 0;

		originalVolume = volume;

		if (filterEnabled)
		{
			// Get rid of the filtered volume
			delete this->volume;
			this->volume = 0;
		}

		if (filter)
		{
			// Setup the filter
			bool res = filter->Setup(volume);
			if (!res)
			{
				std::cerr << "Error setting up filter" << std::endl;
				delete filter;
				filter = 0;
			}
		}

		return old;
	}

	// ------------------------------------------------------------------------
	void FilteredVolumeParamSet::SetFilterEnabled(bool enabled)
	{
		if (enabled == filterEnabled) return;

		if (!filter)
		{
			filterEnabled = false;
			return;
		}

		filterEnabled = enabled;

		if (enabled)
		{
			// Turn on filtering
			volume = 0;
			Update();
		}
		else
		{
			// Delete filtered volume
			delete volume;
			volume = originalVolume;
		}
	}

	// ------------------------------------------------------------------------
	void FilteredVolumeParamSet::Update()
	{
		if (filterEnabled)
		{
			filter->scale = scale;
			volume = filter->Execute(volume);
		}
	}
}
<|endoftext|>


<commit_before>/*
    This file is part of Kontact.
    Copyright (c) 2003 Kontact Developer

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qwidget.h>
#include <qdragobject.h>

#include <kaction.h>
#include <kdebug.h>
#include <kgenericfactory.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include "core.h"
#include "summarywidget.h"

#include "korganizerplugin.h"

typedef KGenericFactory< KOrganizerPlugin, Kontact::Core > KOrganizerPluginFactory;
K_EXPORT_COMPONENT_FACTORY( libkontact_korganizerplugin,
                            KOrganizerPluginFactory( "kontact_korganizerplugin" ) )

KOrganizerPlugin::KOrganizerPlugin( Kontact::Core *core, const char *, const QStringList& )
  : Kontact::Plugin( core, core, "korganizer" ),
    mIface( 0 )
{
  setInstance( KOrganizerPluginFactory::instance() );

  insertNewAction( new KAction( i18n( "New Event" ), BarIcon( "event" ),
                   0, this, SLOT( slotNewEvent() ), actionCollection(),
                   "new_event" ) );
}

KOrganizerPlugin::~KOrganizerPlugin()
{
}

Kontact::Summary *KOrganizerPlugin::createSummaryWidget( QWidget *parent )
{
  return new SummaryWidget( this, parent );
}

KParts::Part *KOrganizerPlugin::createPart()
{
  KParts::Part * part = loadPart();
  if ( !part ) return 0;

  (void) dcopClient(); // ensure that we register to DCOP as "korganizer"
  mIface = new KCalendarIface_stub( dcopClient(), "kontact", "CalendarIface" );

  return part;
}

QString KOrganizerPlugin::tipFile() const
{
  QString file = ::locate("data", "korganizer/tips");
  return file;
}

void KOrganizerPlugin::select()
{
  if ( mIface ) mIface->showEventView();
}

void KOrganizerPlugin::slotNewEvent()
{
  part();
  if ( !mIface )
    return;
}

bool KOrganizerPlugin::createDCOPInterface( const QString& serviceType )
{
  kdDebug(5602) << k_funcinfo << serviceType << endl;
  if ( serviceType == "DCOP/Organizer" || serviceType == "DCOP/Calendar" ) {
    if ( part() )
      return true;
  }

  return false;
}

bool KOrganizerPlugin::canDecodeDrag( QMimeSource *mimeSource )
{
  return QTextDrag::canDecode( mimeSource );
}

void KOrganizerPlugin::processDropEvent( QDropEvent *event )
{
  QString text;
  if ( QTextDrag::decode( event, text ) ) {
    kdDebug() << "DROP:" << text << endl;
    if ( mIface ) mIface->openEventEditor( text );
    else kdError() << "KOrganizer Part not loaded." << endl;
  } else {
    KMessageBox::sorry( core(), i18n("Can't handle drop events of type '%1'.")
                                .arg( event->format() ) );
  }
}

#include "korganizerplugin.moc"
<commit_msg>Add support for "x-kmail-drag/message-list" drops.<commit_after>/*
    This file is part of Kontact.
    Copyright (c) 2003 Kontact Developer

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qwidget.h>
#include <qdragobject.h>

#include <kaction.h>
#include <kdebug.h>
#include <kgenericfactory.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include <libkdepim/maillistdrag.h>

#include "core.h"
#include "summarywidget.h"

#include "korganizerplugin.h"

typedef KGenericFactory< KOrganizerPlugin, Kontact::Core > KOrganizerPluginFactory;
K_EXPORT_COMPONENT_FACTORY( libkontact_korganizerplugin,
                            KOrganizerPluginFactory( "kontact_korganizerplugin" ) )

KOrganizerPlugin::KOrganizerPlugin( Kontact::Core *core, const char *, const QStringList& )
  : Kontact::Plugin( core, core, "korganizer" ),
    mIface( 0 )
{
  setInstance( KOrganizerPluginFactory::instance() );

  insertNewAction( new KAction( i18n( "New Event" ), BarIcon( "event" ),
                   0, this, SLOT( slotNewEvent() ), actionCollection(),
                   "new_event" ) );
}

KOrganizerPlugin::~KOrganizerPlugin()
{
}

Kontact::Summary *KOrganizerPlugin::createSummaryWidget( QWidget *parent )
{
  return new SummaryWidget( this, parent );
}

KParts::Part *KOrganizerPlugin::createPart()
{
  KParts::Part * part = loadPart();
  if ( !part ) return 0;

  (void) dcopClient(); // ensure that we register to DCOP as "korganizer"
  mIface = new KCalendarIface_stub( dcopClient(), "kontact", "CalendarIface" );

  return part;
}

QString KOrganizerPlugin::tipFile() const
{
  QString file = ::locate("data", "korganizer/tips");
  return file;
}

void KOrganizerPlugin::select()
{
  if ( mIface ) mIface->showEventView();
}

void KOrganizerPlugin::slotNewEvent()
{
  part();
  if ( !mIface )
    return;
}

bool KOrganizerPlugin::createDCOPInterface( const QString& serviceType )
{
  kdDebug(5602) << k_funcinfo << serviceType << endl;
  if ( serviceType == "DCOP/Organizer" || serviceType == "DCOP/Calendar" ) {
    if ( part() )
      return true;
  }

  return false;
}

bool KOrganizerPlugin::canDecodeDrag( QMimeSource *mimeSource )
{
  return QTextDrag::canDecode( mimeSource ) ||
         KPIM::MailListDrag::canDecode( mimeSource );
}

void KOrganizerPlugin::processDropEvent( QDropEvent *event )
{
  if ( !mIface ) {
    kdError() << "KOrganizer Part not loaded." << endl;
    return;
  }

  QString text;
  if ( QTextDrag::decode( event, text ) ) {
    kdDebug() << "DROP:" << text << endl;
    mIface->openEventEditor( text );
    return;
  }

  KPIM::MailList mails;
  if ( KPIM::MailListDrag::decode( event, mails ) ) {
    if ( mails.count() != 1 ) {
      KMessageBox::sorry( core(),
                          i18n("Drops of multiple mails aren't supported." ) );
    } else {
      KPIM::MailSummary mail = mails.first();
      mIface->openEventEditor( mail.subject() );
    }
    return;
  }

  KMessageBox::sorry( core(), i18n("Can't handle drop events of type '%1'.")
                              .arg( event->format() ) );
}

#include "korganizerplugin.moc"
<|endoftext|>