diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index a7a694463e..d9e271498f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -24,7 +24,7 @@ opencs_units (model/world opencs_units_noqt (model/world universalid record commands columnbase scriptcontext cell refidcollection - refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata + refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection ) opencs_hdrs_noqt (model/world diff --git a/apps/opencs/model/world/cellcoordinates.cpp b/apps/opencs/model/world/cellcoordinates.cpp new file mode 100644 index 0000000000..b1c8441e63 --- /dev/null +++ b/apps/opencs/model/world/cellcoordinates.cpp @@ -0,0 +1,60 @@ + +#include "cellcoordinates.hpp" + +#include +#include + +CSMWorld::CellCoordinates::CellCoordinates() : mX (0), mY (0) {} + +CSMWorld::CellCoordinates::CellCoordinates (int x, int y) : mX (x), mY (y) {} + +int CSMWorld::CellCoordinates::getX() const +{ + return mX; +} + +int CSMWorld::CellCoordinates::getY() const +{ + return mY; +} + +CSMWorld::CellCoordinates CSMWorld::CellCoordinates::move (int x, int y) const +{ + return CellCoordinates (mX + x, mY + y); +} + +std::string CSMWorld::CellCoordinates::getId (const std::string& worldspace) const +{ + // we ignore the worldspace for now, since there is only one (will change in 1.1) + std::ostringstream stream; + + stream << "#" << mX << " " << mY; + + return stream.str(); +} + +bool CSMWorld::operator== (const CellCoordinates& left, const CellCoordinates& right) +{ + return left.getX()==right.getX() && left.getY()==right.getY(); +} + +bool CSMWorld::operator!= (const CellCoordinates& left, const CellCoordinates& right) +{ + return !(left==right); +} + +bool CSMWorld::operator< (const CellCoordinates& left, const CellCoordinates& right) +{ + if (left.getX()right.getX()) + return false; + + return left.getY() +#include + +#include + +namespace CSMWorld +{ + class CellCoordinates + { + int mX; + int mY; + + public: + + CellCoordinates(); + + CellCoordinates (int x, int y); + + int getX() const; + + int getY() const; + + CellCoordinates move (int x, int y) const; + ///< Return a copy of *this, moved by the given offset. + + std::string getId (const std::string& worldspace) const; + ///< Return the ID for the cell at these coordinates. + }; + + bool operator== (const CellCoordinates& left, const CellCoordinates& right); + bool operator!= (const CellCoordinates& left, const CellCoordinates& right); + bool operator< (const CellCoordinates& left, const CellCoordinates& right); + + std::ostream& operator<< (std::ostream& stream, const CellCoordinates& coordiantes); +} + +Q_DECLARE_METATYPE (CSMWorld::CellCoordinates) + +#endif diff --git a/apps/opencs/model/world/cellselection.cpp b/apps/opencs/model/world/cellselection.cpp new file mode 100644 index 0000000000..73b5196f13 --- /dev/null +++ b/apps/opencs/model/world/cellselection.cpp @@ -0,0 +1,83 @@ + +#include "cellselection.hpp" + +#include +#include +#include + +CSMWorld::CellSelection::Iterator CSMWorld::CellSelection::begin() const +{ + return mCells.begin(); +} + +CSMWorld::CellSelection::Iterator CSMWorld::CellSelection::end() const +{ + return mCells.end(); +} + +bool CSMWorld::CellSelection::add (const CellCoordinates& coordinates) +{ + return mCells.insert (coordinates).second; +} + +void CSMWorld::CellSelection::remove (const CellCoordinates& coordinates) +{ + mCells.erase (coordinates); +} + +bool CSMWorld::CellSelection::has (const CellCoordinates& coordinates) const +{ + return mCells.find (coordinates)!=end(); +} + +int CSMWorld::CellSelection::getSize() const +{ + return mCells.size(); +} + +CSMWorld::CellCoordinates CSMWorld::CellSelection::getCentre() const +{ + if (mCells.empty()) + throw std::logic_error ("call of getCentre on empty cell selection"); + + double x = 0; + double y = 0; + + for (Iterator iter = begin(); iter!=end(); ++iter) + { + x += iter->getX(); + y += iter->getY(); + } + + x /= mCells.size(); + y /= mCells.size(); + + Iterator closest = begin(); + double distance = std::numeric_limits::max(); + + for (Iterator iter (begin()); iter!=end(); ++iter) + { + double deltaX = x - iter->getX(); + double deltaY = y - iter->getY(); + + double delta = std::sqrt (deltaX * deltaX + deltaY * deltaY); + + if (deltamove (x, y)); + + mCells.swap (moved); +} diff --git a/apps/opencs/model/world/cellselection.hpp b/apps/opencs/model/world/cellselection.hpp new file mode 100644 index 0000000000..042416a33f --- /dev/null +++ b/apps/opencs/model/world/cellselection.hpp @@ -0,0 +1,57 @@ +#ifndef CSM_WOLRD_CELLSELECTION_H +#define CSM_WOLRD_CELLSELECTION_H + +#include + +#include + +#include "cellcoordinates.hpp" + +namespace CSMWorld +{ + /// \brief Selection of cells in a paged worldspace + /// + /// \note The CellSelection does not specify the worldspace it applies to. + class CellSelection + { + public: + + typedef std::set Container; + typedef Container::const_iterator Iterator; + + private: + + Container mCells; + + public: + + Iterator begin() const; + + Iterator end() const; + + bool add (const CellCoordinates& coordinates); + ///< Ignored if the cell specified by \a coordinates is already part of the selection. + /// + /// \return Was a cell added to the collection? + + void remove (const CellCoordinates& coordinates); + ///< ignored if the cell specified by \a coordinates is not part of the selection. + + bool has (const CellCoordinates& coordinates) const; + ///< \return Is the cell specified by \a coordinates part of the selection? + + int getSize() const; + ///< Return number of cells. + + CellCoordinates getCentre() const; + ///< Return the selected cell that is closest to the geometric centre of the selection. + /// + /// \attention This function must not be called on selections that are empty. + + void move (int x, int y); + }; +} + +Q_DECLARE_METATYPE (CSMWorld::CellSelection) + +#endif