SWORD25: Enforced code naming conventions in math/*

svn-id: r53392
This commit is contained in:
Eugene Sandulenko 2010-10-03 13:25:36 +00:00
parent 54ccc8f4c9
commit 063cb5d84c
26 changed files with 978 additions and 1234 deletions

View File

@ -797,7 +797,7 @@ bool Animation::unpersist(InputPersistenceBlock &reader) {
AnimationDescription *Animation::GetAnimationDescription() const {
if (m_AnimationResourcePtr) return m_AnimationResourcePtr;
else return AnimationTemplateRegistry::GetInstance().resolveHandle(m_AnimationTemplateHandle);
else return AnimationTemplateRegistry::getInstance().resolveHandle(m_AnimationTemplateHandle);
}
} // End of namespace Sword25

View File

@ -57,7 +57,7 @@ uint AnimationTemplate::Create(const Common::String &SourceAnimation) {
AnimationTemplate *AnimationTemplatePtr = new AnimationTemplate(SourceAnimation);
if (AnimationTemplatePtr->isValid()) {
return AnimationTemplateRegistry::GetInstance().ResolvePtr(AnimationTemplatePtr);
return AnimationTemplateRegistry::getInstance().resolvePtr(AnimationTemplatePtr);
} else {
delete AnimationTemplatePtr;
return 0;
@ -70,7 +70,7 @@ uint AnimationTemplate::Create(const AnimationTemplate &Other) {
AnimationTemplate *AnimationTemplatePtr = new AnimationTemplate(Other);
if (AnimationTemplatePtr->isValid()) {
return AnimationTemplateRegistry::GetInstance().ResolvePtr(AnimationTemplatePtr);
return AnimationTemplateRegistry::getInstance().resolvePtr(AnimationTemplatePtr);
} else {
delete AnimationTemplatePtr;
return 0;
@ -83,7 +83,7 @@ uint AnimationTemplate::Create(InputPersistenceBlock &Reader, uint Handle) {
AnimationTemplate *AnimationTemplatePtr = new AnimationTemplate(Reader, Handle);
if (AnimationTemplatePtr->isValid()) {
return AnimationTemplateRegistry::GetInstance().ResolvePtr(AnimationTemplatePtr);
return AnimationTemplateRegistry::getInstance().resolvePtr(AnimationTemplatePtr);
} else {
delete AnimationTemplatePtr;
return 0;
@ -94,7 +94,7 @@ uint AnimationTemplate::Create(InputPersistenceBlock &Reader, uint Handle) {
AnimationTemplate::AnimationTemplate(const Common::String &SourceAnimation) {
// Objekt registrieren.
AnimationTemplateRegistry::GetInstance().RegisterObject(this);
AnimationTemplateRegistry::getInstance().registerObject(this);
_valid = false;
@ -109,7 +109,7 @@ AnimationTemplate::AnimationTemplate(const Common::String &SourceAnimation) {
AnimationTemplate::AnimationTemplate(const AnimationTemplate &Other) : AnimationDescription(){
// Objekt registrieren.
AnimationTemplateRegistry::GetInstance().RegisterObject(this);
AnimationTemplateRegistry::getInstance().registerObject(this);
_valid = false;
@ -135,7 +135,7 @@ AnimationTemplate::AnimationTemplate(const AnimationTemplate &Other) : Animation
AnimationTemplate::AnimationTemplate(InputPersistenceBlock &Reader, uint Handle) {
// Objekt registrieren.
AnimationTemplateRegistry::GetInstance().RegisterObject(this, Handle);
AnimationTemplateRegistry::getInstance().registerObject(this, Handle);
// Objekt laden.
_valid = unpersist(Reader);
@ -162,7 +162,7 @@ AnimationTemplate::~AnimationTemplate() {
}
// Objekt deregistrieren
AnimationTemplateRegistry::GetInstance().DeregisterObject(this);
AnimationTemplateRegistry::getInstance().deregisterObject(this);
}
// -----------------------------------------------------------------------------

View File

@ -32,16 +32,8 @@
*
*/
// -----------------------------------------------------------------------------
// Logging
// -----------------------------------------------------------------------------
#define BS_LOG_PREFIX "ANIMATIONTEMPLATEREGISTRY"
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include "sword25/kernel/outputpersistenceblock.h"
#include "sword25/kernel/inputpersistenceblock.h"
#include "sword25/gfx/animationtemplateregistry.h"
@ -49,71 +41,67 @@
namespace Sword25 {
Common::ScopedPtr<AnimationTemplateRegistry> AnimationTemplateRegistry::m_InstancePtr;
Common::ScopedPtr<AnimationTemplateRegistry> AnimationTemplateRegistry::_instancePtr;
void AnimationTemplateRegistry::LogErrorLn(const char *Message) const {
BS_LOG_ERRORLN(Message);
void AnimationTemplateRegistry::logErrorLn(const char *message) const {
BS_LOG_ERRORLN(message);
}
// -----------------------------------------------------------------------------
void AnimationTemplateRegistry::LogWarningLn(const char *Message) const {
BS_LOG_WARNINGLN(Message);
void AnimationTemplateRegistry::logWarningLn(const char *message) const {
BS_LOG_WARNINGLN(message);
}
// -----------------------------------------------------------------------------
bool AnimationTemplateRegistry::persist(OutputPersistenceBlock &writer) {
bool Result = true;
bool result = true;
// Das nächste zu vergebene Handle schreiben.
writer.write(m_NextHandle);
writer.write(_nextHandle);
// Anzahl an BS_AnimationTemplates schreiben.
writer.write(m_Handle2PtrMap.size());
writer.write(_handle2PtrMap.size());
// Alle BS_AnimationTemplates persistieren.
HANDLE2PTR_MAP::const_iterator Iter = m_Handle2PtrMap.begin();
while (Iter != m_Handle2PtrMap.end()) {
HANDLE2PTR_MAP::const_iterator iter = _handle2PtrMap.begin();
while (iter != _handle2PtrMap.end()) {
// Handle persistieren.
writer.write(Iter->_key);
writer.write(iter->_key);
// Objekt persistieren.
Result &= Iter->_value->persist(writer);
result &= iter->_value->persist(writer);
++Iter;
++iter;
}
return Result;
return result;
}
// -----------------------------------------------------------------------------
bool AnimationTemplateRegistry::unpersist(InputPersistenceBlock &reader) {
bool Result = true;
bool result = true;
// Das nächste zu vergebene Handle wieder herstellen.
reader.read(m_NextHandle);
reader.read(_nextHandle);
// Alle vorhandenen BS_AnimationTemplates zerstören.
while (!m_Handle2PtrMap.empty())
delete m_Handle2PtrMap.begin()->_value;
while (!_handle2PtrMap.empty())
delete _handle2PtrMap.begin()->_value;
// Anzahl an BS_AnimationTemplates einlesen.
uint AnimationTemplateCount;
reader.read(AnimationTemplateCount);
uint animationTemplateCount;
reader.read(animationTemplateCount);
// Alle gespeicherten BS_AnimationTemplates wieder herstellen.
for (uint i = 0; i < AnimationTemplateCount; ++i) {
for (uint i = 0; i < animationTemplateCount; ++i) {
// Handle lesen.
uint Handle;
reader.read(Handle);
uint handle;
reader.read(handle);
// BS_AnimationTemplate wieder herstellen.
Result &= (AnimationTemplate::Create(reader, Handle) != 0);
result &= (AnimationTemplate::Create(reader, handle) != 0);
}
return reader.isGood() && Result;
return reader.isGood() && result;
}
} // End of namespace Sword25

View File

@ -35,10 +35,6 @@
#ifndef SWORD25_ANIMATIONTEMPLATEREGISTRY_H
#define SWORD25_ANIMATIONTEMPLATEREGISTRY_H
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include "sword25/kernel/common.h"
#include "sword25/kernel/persistable.h"
#include "sword25/kernel/objectregistry.h"
@ -47,31 +43,24 @@
namespace Sword25 {
// -----------------------------------------------------------------------------
// Forward Deklarationen
// -----------------------------------------------------------------------------
class AnimationTemplate;
// -----------------------------------------------------------------------------
// Klassendeklaration
// -----------------------------------------------------------------------------
class AnimationTemplateRegistry : public ObjectRegistry<AnimationTemplate>, public Persistable {
public:
static AnimationTemplateRegistry &GetInstance() {
if (!m_InstancePtr.get()) m_InstancePtr.reset(new AnimationTemplateRegistry);
return *m_InstancePtr.get();
static AnimationTemplateRegistry &getInstance() {
if (!_instancePtr.get())
_instancePtr.reset(new AnimationTemplateRegistry);
return *_instancePtr.get();
}
virtual bool persist(OutputPersistenceBlock &Writer);
virtual bool unpersist(InputPersistenceBlock &Reader);
virtual bool persist(OutputPersistenceBlock &writer);
virtual bool unpersist(InputPersistenceBlock &reader);
private:
virtual void LogErrorLn(const char *Message) const;
virtual void LogWarningLn(const char *Message) const;
virtual void logErrorLn(const char *message) const;
virtual void logWarningLn(const char *message) const;
static Common::ScopedPtr<AnimationTemplateRegistry> m_InstancePtr;
static Common::ScopedPtr<AnimationTemplateRegistry> _instancePtr;
};
} // End of namespace Sword25

View File

@ -144,7 +144,7 @@ static AnimationTemplate *CheckAnimationTemplate(lua_State *L, int idx = 1) {
// Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.AnimationTemplate
uint AnimationTemplateHandle;
if ((AnimationTemplateHandle = *reinterpret_cast<uint *>(my_checkudata(L, idx, ANIMATION_TEMPLATE_CLASS_NAME))) != 0) {
AnimationTemplate *AnimationTemplatePtr = AnimationTemplateRegistry::GetInstance().resolveHandle(AnimationTemplateHandle);
AnimationTemplate *AnimationTemplatePtr = AnimationTemplateRegistry::getInstance().resolveHandle(AnimationTemplateHandle);
if (!AnimationTemplatePtr)
luaL_error(L, "The animation template with the handle %d does no longer exist.", AnimationTemplateHandle);
return AnimationTemplatePtr;
@ -159,7 +159,7 @@ static AnimationTemplate *CheckAnimationTemplate(lua_State *L, int idx = 1) {
static int NewAnimationTemplate(lua_State *L) {
uint AnimationTemplateHandle = AnimationTemplate::Create(luaL_checkstring(L, 1));
AnimationTemplate *AnimationTemplatePtr = AnimationTemplateRegistry::GetInstance().resolveHandle(AnimationTemplateHandle);
AnimationTemplate *AnimationTemplatePtr = AnimationTemplateRegistry::getInstance().resolveHandle(AnimationTemplateHandle);
if (AnimationTemplatePtr && AnimationTemplatePtr->isValid()) {
NewUintUserData(L, AnimationTemplateHandle);
//luaL_getmetatable(L, ANIMATION_TEMPLATE_CLASS_NAME);
@ -348,8 +348,8 @@ static int DrawDebugLine(lua_State *L) {
Vertex Start;
Vertex End;
Vertex::LuaVertexToVertex(L, 1, Start);
Vertex::LuaVertexToVertex(L, 2, End);
Vertex::luaVertexToVertex(L, 1, Start);
Vertex::luaVertexToVertex(L, 2, End);
pGE->DrawDebugLine(Start, End, GraphicEngine::LuaColorToARGBColor(L, 3));
return 0;
@ -539,8 +539,8 @@ static int RO_SetPos(lua_State *L) {
RenderObjectPtr<RenderObject> ROPtr = CheckRenderObject(L);
BS_ASSERT(ROPtr.isValid());
Vertex Pos;
Vertex::LuaVertexToVertex(L, 2, Pos);
ROPtr->setPos(Pos.X, Pos.Y);
Vertex::luaVertexToVertex(L, 2, Pos);
ROPtr->setPos(Pos.x, Pos.y);
return 0;
}
@ -968,8 +968,8 @@ static int B_GetPixel(lua_State *L) {
RenderObjectPtr<Bitmap> BitmapPtr = CheckBitmap(L);
BS_ASSERT(BitmapPtr.isValid());
Vertex Pos;
Vertex::LuaVertexToVertex(L, 2, Pos);
GraphicEngine::ARGBColorToLuaColor(L, BitmapPtr->getPixel(Pos.X, Pos.Y));
Vertex::luaVertexToVertex(L, 2, Pos);
GraphicEngine::ARGBColorToLuaColor(L, BitmapPtr->getPixel(Pos.x, Pos.y));
return 1;
}

View File

@ -76,9 +76,9 @@ RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type,
// Renderobject registrieren, abhängig vom Handle-Parameter entweder mit beliebigem oder vorgegebenen Handle.
if (handle == 0)
_handle = RenderObjectRegistry::GetInstance().RegisterObject(this);
_handle = RenderObjectRegistry::getInstance().registerObject(this);
else
_handle = RenderObjectRegistry::GetInstance().RegisterObject(this, handle);
_handle = RenderObjectRegistry::getInstance().registerObject(this, handle);
if (_handle == 0)
return;
@ -110,7 +110,7 @@ RenderObject::~RenderObject() {
deleteAllChildren();
// Objekt deregistrieren.
RenderObjectRegistry::GetInstance().DeregisterObject(this);
RenderObjectRegistry::getInstance().deregisterObject(this);
}
// Rendern

View File

@ -32,10 +32,6 @@
*
*/
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include "sword25/gfx/renderobjectmanager.h"
#include "sword25/kernel/kernel.h"
@ -52,27 +48,17 @@ namespace Sword25 {
#define BS_LOG_PREFIX "RENDEROBJECTMANAGER"
// -----------------------------------------------------------------------------
// Konstruktion / Desktruktion
// -----------------------------------------------------------------------------
RenderObjectManager::RenderObjectManager(int width, int height, int framebufferCount) :
_frameStarted(false) {
// Wurzel des BS_RenderObject-Baumes erzeugen.
_rootPtr = (new RootRenderObject(this, width, height))->getHandle();
}
// -----------------------------------------------------------------------------
RenderObjectManager::~RenderObjectManager() {
// Die Wurzel des Baumes löschen, damit werden alle BS_RenderObjects mitgelöscht.
_rootPtr.erase();
}
// -----------------------------------------------------------------------------
// Interface
// -----------------------------------------------------------------------------
void RenderObjectManager::startFrame() {
_frameStarted = true;
@ -85,8 +71,6 @@ void RenderObjectManager::startFrame() {
(*iter)->frameNotification(timeElapsed);
}
// -----------------------------------------------------------------------------
bool RenderObjectManager::render() {
// Den Objekt-Status des Wurzelobjektes aktualisieren. Dadurch werden rekursiv alle Baumelemente aktualisiert.
// Beim aktualisieren des Objekt-Status werden auch die Update-Rects gefunden, so dass feststeht, was neu gezeichnet
@ -100,14 +84,10 @@ bool RenderObjectManager::render() {
return _rootPtr->render();
}
// -----------------------------------------------------------------------------
void RenderObjectManager::attatchTimedRenderObject(RenderObjectPtr<TimedRenderObject> renderObjectPtr) {
_timedRenderObjects.push_back(renderObjectPtr);
}
// -----------------------------------------------------------------------------
void RenderObjectManager::detatchTimedRenderObject(RenderObjectPtr<TimedRenderObject> renderObjectPtr) {
for (uint i = 0; i < _timedRenderObjects.size(); i++)
if (_timedRenderObjects[i] == renderObjectPtr) {
@ -116,10 +96,6 @@ void RenderObjectManager::detatchTimedRenderObject(RenderObjectPtr<TimedRenderOb
}
}
// -----------------------------------------------------------------------------
// Persistenz
// -----------------------------------------------------------------------------
bool RenderObjectManager::persist(OutputPersistenceBlock &writer) {
bool result = true;
@ -137,13 +113,11 @@ bool RenderObjectManager::persist(OutputPersistenceBlock &writer) {
}
// Alle BS_AnimationTemplates persistieren.
result &= AnimationTemplateRegistry::GetInstance().persist(writer);
result &= AnimationTemplateRegistry::getInstance().persist(writer);
return result;
}
// -----------------------------------------------------------------------------
bool RenderObjectManager::unpersist(InputPersistenceBlock &reader) {
bool result = true;
@ -169,7 +143,7 @@ bool RenderObjectManager::unpersist(InputPersistenceBlock &reader) {
}
// Alle BS_AnimationTemplates wieder herstellen.
result &= AnimationTemplateRegistry::GetInstance().unpersist(reader);
result &= AnimationTemplateRegistry::getInstance().unpersist(reader);
return result;
}

View File

@ -44,16 +44,8 @@
namespace Sword25 {
// -----------------------------------------------------------------------------
// Forward Declarations
// -----------------------------------------------------------------------------
class RenderObject;
// -----------------------------------------------------------------------------
// Klassendeklaration
// -----------------------------------------------------------------------------
template<class T>
class RenderObjectPtr {
public:
@ -62,7 +54,7 @@ public:
RenderObjectPtr(uint handle) : _handle(handle) {}
T *operator->() const {
return static_cast<T *>(RenderObjectRegistry::GetInstance().resolveHandle(_handle));
return static_cast<T *>(RenderObjectRegistry::getInstance().resolveHandle(_handle));
}
bool operator==(const RenderObjectPtr<T> & other) {
@ -70,11 +62,11 @@ public:
}
bool isValid() const {
return RenderObjectRegistry::GetInstance().resolveHandle(_handle) != 0;
return RenderObjectRegistry::getInstance().resolveHandle(_handle) != 0;
}
void erase() {
delete static_cast<T *>(RenderObjectRegistry::GetInstance().resolveHandle(_handle));
delete static_cast<T *>(RenderObjectRegistry::getInstance().resolveHandle(_handle));
_handle = 0;
}

View File

@ -32,32 +32,22 @@
*
*/
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include "sword25/gfx/renderobjectregistry.h"
#include "common/ptr.h"
namespace Sword25 {
// -----------------------------------------------------------------------------
// Logging
// -----------------------------------------------------------------------------
#define BS_LOG_PREFIX "RENDEROBJECTREGISTRY"
Common::ScopedPtr<RenderObjectRegistry> RenderObjectRegistry::m_InstancePtr;
Common::ScopedPtr<RenderObjectRegistry> RenderObjectRegistry::_instancePtr;
void RenderObjectRegistry::LogErrorLn(const char *Message) const {
BS_LOG_ERRORLN(Message);
void RenderObjectRegistry::logErrorLn(const char *message) const {
BS_LOG_ERRORLN(message);
}
// -----------------------------------------------------------------------------
void RenderObjectRegistry::LogWarningLn(const char *Message) const {
BS_LOG_WARNINGLN(Message);
void RenderObjectRegistry::logWarningLn(const char *message) const {
BS_LOG_WARNINGLN(message);
}
} // End of namespace Sword25

View File

@ -58,18 +58,19 @@ class RenderObject;
class RenderObjectRegistry : public ObjectRegistry<RenderObject> {
public:
static RenderObjectRegistry &GetInstance() {
if (!m_InstancePtr.get()) m_InstancePtr.reset(new RenderObjectRegistry);
return *m_InstancePtr.get();
static RenderObjectRegistry &getInstance() {
if (!_instancePtr.get())
_instancePtr.reset(new RenderObjectRegistry);
return *_instancePtr.get();
}
virtual ~RenderObjectRegistry() {}
private:
virtual void LogErrorLn(const char *Message) const;
virtual void LogWarningLn(const char *Message) const;
virtual void logErrorLn(const char *message) const;
virtual void logWarningLn(const char *message) const;
static Common::ScopedPtr<RenderObjectRegistry> m_InstancePtr;
static Common::ScopedPtr<RenderObjectRegistry> _instancePtr;
};
} // End of namespace Sword25

View File

@ -35,10 +35,6 @@
#ifndef SWORD25_OBJECTREGISTRY_H
#define SWORD25_OBJECTREGISTRY_H
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include "common/func.h"
#include "common/hashmap.h"
#include "sword25/kernel/bs_stdint.h"
@ -46,105 +42,92 @@
namespace Sword25 {
// -----------------------------------------------------------------------------
// Klassendeklaration
// -----------------------------------------------------------------------------
template<typename T>
class ObjectRegistry {
public:
ObjectRegistry() : m_NextHandle(1) {}
ObjectRegistry() : _nextHandle(1) {}
virtual ~ObjectRegistry() {}
// -------------------------------------------------------------------------
uint RegisterObject(T *ObjectPtr) {
uint registerObject(T *objectPtr) {
// Null-Pointer können nicht registriert werden.
if (ObjectPtr == 0) {
LogErrorLn("Cannot register a null pointer.");
if (objectPtr == 0) {
logErrorLn("Cannot register a null pointer.");
return 0;
}
// Falls das Objekt bereits registriert wurde, wird eine Warnung ausgeben und das Handle zurückgeben.
uint Handle = FindHandleByPtr(ObjectPtr);
if (Handle != 0) {
LogWarningLn("Tried to register a object that was already registered.");
return Handle;
uint handle = findHandleByPtr(objectPtr);
if (handle != 0) {
logWarningLn("Tried to register a object that was already registered.");
return handle;
}
// Ansonsten wird das Objekt in beide Maps eingetragen und das neue Handle zurückgeben.
else {
m_Handle2PtrMap[m_NextHandle] = ObjectPtr;
m_Ptr2HandleMap[ObjectPtr] = m_NextHandle;
_handle2PtrMap[_nextHandle] = objectPtr;
_ptr2HandleMap[objectPtr] = _nextHandle;
return m_NextHandle++;
return _nextHandle++;
}
}
// -----------------------------------------------------------------------------
uint RegisterObject(T *ObjectPtr, uint Handle) {
uint registerObject(T *objectPtr, uint handle) {
// Null-Pointer und Null-Handle können nicht registriert werden.
if (ObjectPtr == 0 || Handle == 0) {
LogErrorLn("Cannot register a null pointer or a null handle.");
if (objectPtr == 0 || handle == 0) {
logErrorLn("Cannot register a null pointer or a null handle.");
return 0;
}
// Falls das Objekt bereits registriert wurde, wird ein Fehler ausgegeben und 0 zurückgeben.
uint HandleTest = FindHandleByPtr(ObjectPtr);
if (HandleTest != 0) {
LogErrorLn("Tried to register a object that was already registered.");
uint handleTest = findHandleByPtr(objectPtr);
if (handleTest != 0) {
logErrorLn("Tried to register a object that was already registered.");
return 0;
}
// Falls das Handle bereits vergeben ist, wird ein Fehler ausgegeben und 0 zurückgegeben.
else if (FindPtrByHandle(Handle) != 0) {
LogErrorLn("Tried to register a handle that is already taken.");
else if (findPtrByHandle(handle) != 0) {
logErrorLn("Tried to register a handle that is already taken.");
return 0;
}
// Ansonsten wird das Objekt in beide Maps eingetragen und das gewünschte Handle zurückgeben.
else {
m_Handle2PtrMap[Handle] = ObjectPtr;
m_Ptr2HandleMap[ObjectPtr] = Handle;
_handle2PtrMap[handle] = objectPtr;
_ptr2HandleMap[objectPtr] = handle;
// Falls das vergebene Handle größer oder gleich dem nächsten automatische vergebenen Handle ist, wird das nächste automatisch
// vergebene Handle erhöht.
if (Handle >= m_NextHandle) m_NextHandle = Handle + 1;
if (handle >= _nextHandle)
_nextHandle = handle + 1;
return Handle;
return handle;
}
}
// -----------------------------------------------------------------------------
void deregisterObject(T *objectPtr) {
uint handle = findHandleByPtr(objectPtr);
void DeregisterObject(T *ObjectPtr) {
uint Handle = FindHandleByPtr(ObjectPtr);
if (Handle != 0) {
if (handle != 0) {
// Registriertes Objekt aus beiden Maps entfernen.
m_Handle2PtrMap.erase(FindHandleByPtr(ObjectPtr));
m_Ptr2HandleMap.erase(ObjectPtr);
_handle2PtrMap.erase(findHandleByPtr(objectPtr));
_ptr2HandleMap.erase(objectPtr);
} else {
LogWarningLn("Tried to remove a object that was not registered.");
logWarningLn("Tried to remove a object that was not registered.");
}
}
// -----------------------------------------------------------------------------
T *resolveHandle(uint Handle) {
T *resolveHandle(uint handle) {
// Zum Handle gehöriges Objekt in der Hash-Map finden.
T *ObjectPtr = FindPtrByHandle(Handle);
T *objectPtr = findPtrByHandle(handle);
// Pointer zurückgeben. Im Fehlerfall ist dieser 0.
return ObjectPtr;
return objectPtr;
}
// -----------------------------------------------------------------------------
uint ResolvePtr(T *ObjectPtr) {
uint resolvePtr(T *objectPtr) {
// Zum Pointer gehöriges Handle in der Hash-Map finden.
uint Handle = FindHandleByPtr(ObjectPtr);
uint handle = findHandleByPtr(objectPtr);
// Handle zurückgeben. Im Fehlerfall ist dieses 0.
return Handle;
return handle;
}
protected:
@ -163,34 +146,28 @@ protected:
typedef Common::HashMap<uint, T *> HANDLE2PTR_MAP;
typedef Common::HashMap<T *, uint, ClassPointer_Hash, ClassPointer_EqualTo> PTR2HANDLE_MAP;
HANDLE2PTR_MAP m_Handle2PtrMap;
PTR2HANDLE_MAP m_Ptr2HandleMap;
uint m_NextHandle;
HANDLE2PTR_MAP _handle2PtrMap;
PTR2HANDLE_MAP _ptr2HandleMap;
uint _nextHandle;
// -----------------------------------------------------------------------------
T *FindPtrByHandle(uint Handle) {
T *findPtrByHandle(uint handle) {
// Zum Handle gehörigen Pointer finden.
typename HANDLE2PTR_MAP::const_iterator it = m_Handle2PtrMap.find(Handle);
typename HANDLE2PTR_MAP::const_iterator it = _handle2PtrMap.find(handle);
// Pointer zurückgeben, oder, falls keiner gefunden wurde, 0 zurückgeben.
return (it != m_Handle2PtrMap.end()) ? it->_value : 0;
return (it != _handle2PtrMap.end()) ? it->_value : 0;
}
// -----------------------------------------------------------------------------
uint FindHandleByPtr(T *ObjectPtr) {
uint findHandleByPtr(T *objectPtr) {
// Zum Pointer gehöriges Handle finden.
typename PTR2HANDLE_MAP::const_iterator it = m_Ptr2HandleMap.find(ObjectPtr);
typename PTR2HANDLE_MAP::const_iterator it = _ptr2HandleMap.find(objectPtr);
// Handle zurückgeben, oder, falls keines gefunden wurde, 0 zurückgeben.
return (it != m_Ptr2HandleMap.end()) ? it->_value : 0;
return (it != _ptr2HandleMap.end()) ? it->_value : 0;
}
// -----------------------------------------------------------------------------
virtual void LogErrorLn(const char *Message) const = 0;
virtual void LogWarningLn(const char *Message) const = 0;
virtual void logErrorLn(const char *message) const = 0;
virtual void logWarningLn(const char *message) const = 0;
};
} // End of namespace Sword25

View File

@ -326,7 +326,7 @@ bool PersistenceService::SaveGame(uint SlotID, const Common::String &ScreenshotF
OutputPersistenceBlock Writer;
bool Success = true;
Success &= Kernel::GetInstance()->GetScript()->persist(Writer);
Success &= RegionRegistry::GetInstance().persist(Writer);
Success &= RegionRegistry::getInstance().persist(Writer);
Success &= Kernel::GetInstance()->GetGfx()->persist(Writer);
Success &= Kernel::GetInstance()->GetSfx()->persist(Writer);
Success &= Kernel::GetInstance()->GetInput()->persist(Writer);
@ -445,7 +445,7 @@ bool PersistenceService::LoadGame(uint SlotID) {
bool Success = true;
Success &= Kernel::GetInstance()->GetScript()->unpersist(Reader);
// Muss unbedingt nach Script passieren. Da sonst die bereits wiederhergestellten Regions per Garbage-Collection gekillt werden.
Success &= RegionRegistry::GetInstance().unpersist(Reader);
Success &= RegionRegistry::getInstance().unpersist(Reader);
Success &= Kernel::GetInstance()->GetGfx()->unpersist(Reader);
Success &= Kernel::GetInstance()->GetSfx()->unpersist(Reader);
Success &= Kernel::GetInstance()->GetInput()->unpersist(Reader);

View File

@ -39,7 +39,7 @@ namespace Sword25 {
#define BS_LOG_PREFIX "GEOMETRY"
Geometry::Geometry(Kernel *pKernel) : Service(pKernel) {
if (!_RegisterScriptBindings())
if (!registerScriptBindings())
BS_LOG_ERRORLN("Script bindings could not be registered.");
else
BS_LOGLN("Script bindings registered.");

View File

@ -48,7 +48,7 @@ public:
virtual ~Geometry() {}
private:
bool _RegisterScriptBindings();
bool registerScriptBindings();
};
} // End of namespace Sword25

View File

@ -49,20 +49,12 @@
#include "sword25/math/walkregion.h"
#include "sword25/math/vertex.h"
// -----------------------------------------------------------------------------
namespace Sword25 {
// -----------------------------------------------------------------------------
// Constants
// -----------------------------------------------------------------------------
// These strings are defined as #defines to enable compile-time string composition
#define REGION_CLASS_NAME "Geo.Region"
#define WALKREGION_CLASS_NAME "Geo.WalkRegion"
// -----------------------------------------------------------------------------
// How luaL_checkudata, only without that no error is generated.
static void *my_checkudata(lua_State *L, int ud, const char *tname) {
int top = lua_gettop(L);
@ -84,16 +76,12 @@ static void *my_checkudata(lua_State *L, int ud, const char *tname) {
return NULL;
}
// -----------------------------------------------------------------------------
static void NewUintUserData(lua_State *L, uint Value) {
void *UserData = lua_newuserdata(L, sizeof(Value));
memcpy(UserData, &Value, sizeof(Value));
static void newUintUserData(lua_State *L, uint value) {
void *userData = lua_newuserdata(L, sizeof(value));
memcpy(userData, &value, sizeof(value));
}
// -----------------------------------------------------------------------------
static bool IsValidPolygonDefinition(lua_State *L) {
static bool isValidPolygonDefinition(lua_State *L) {
#ifdef DEBUG
int __startStackDepth = lua_gettop(L);
#endif
@ -104,23 +92,23 @@ static bool IsValidPolygonDefinition(lua_State *L) {
return false;
}
int TableSize = luaL_getn(L, -1);
int tableSize = luaL_getn(L, -1);
// Make sure that there are at least three Vertecies
if (TableSize < 6) {
if (tableSize < 6) {
luaL_error(L, "Invalid polygon definition. At least three vertecies needed.");
return false;
}
// Make sure that the number of table elements is divisible by two.
// Since any two elements is a vertex, an odd number of elements is not allowed
if ((TableSize % 2) != 0) {
if ((tableSize % 2) != 0) {
luaL_error(L, "Invalid polygon definition. Even number of table elements needed.");
return false;
}
// Ensure that all elements in the table are of type Number
for (int i = 1; i <= TableSize; i += 1) {
for (int i = 1; i <= tableSize; i++) {
lua_rawgeti(L, -1, i);
if (!lua_isnumber(L, -1)) {
luaL_error(L, "Invalid polygon definition. All table elements have to be numbers.");
@ -136,9 +124,7 @@ static bool IsValidPolygonDefinition(lua_State *L) {
return true;
}
// -----------------------------------------------------------------------------
static void TablePolygonToPolygon(lua_State *L, Polygon &Polygon) {
static void tablePolygonToPolygon(lua_State *L, Polygon &polygon) {
#ifdef DEBUG
int __startStackDepth = lua_gettop(L);
#endif
@ -146,16 +132,16 @@ static void TablePolygonToPolygon(lua_State *L, Polygon &Polygon) {
// Ensure that a valid polygon definition is on the stack.
// It is not necessary to catch the return value, since all errors are reported on luaL_error
// End script.
IsValidPolygonDefinition(L);
isValidPolygonDefinition(L);
int VertexCount = luaL_getn(L, -1) / 2;
int vertexCount = luaL_getn(L, -1) / 2;
// Memory is reserved for Vertecies
Common::Array<Vertex> Vertecies;
Vertecies.reserve(VertexCount);
Common::Array<Vertex> vertices;
vertices.reserve(vertexCount);
// Create Vertecies
for (int i = 0; i < VertexCount; i++) {
for (int i = 0; i < vertexCount; i++) {
// X Value
lua_rawgeti(L, -1, (i * 2) + 1);
int X = static_cast<int>(lua_tonumber(L, -1));
@ -167,21 +153,19 @@ static void TablePolygonToPolygon(lua_State *L, Polygon &Polygon) {
lua_pop(L, 1);
// Vertex
Vertecies.push_back(Vertex(X, Y));
vertices.push_back(Vertex(X, Y));
}
BS_ASSERT((int)Vertecies.size() == VertexCount);
BS_ASSERT((int)vertices.size() == vertexCount);
#ifdef DEBUG
BS_ASSERT(__startStackDepth == lua_gettop(L));
#endif
// Create polygon
Polygon.Init(VertexCount, &Vertecies[0]);
polygon.init(vertexCount, &vertices[0]);
}
// -----------------------------------------------------------------------------
static uint TableRegionToRegion(lua_State *L, const char *ClassName) {
static uint tableRegionToRegion(lua_State *L, const char *className) {
#ifdef DEBUG
int __startStackDepth = lua_gettop(L);
#endif
@ -199,54 +183,54 @@ static uint TableRegionToRegion(lua_State *L, const char *ClassName) {
return 0;
}
uint RegionHandle = 0;
if (!strcmp(ClassName, REGION_CLASS_NAME)) {
RegionHandle = Region::Create(Region::RT_REGION);
} else if (!strcmp(ClassName, WALKREGION_CLASS_NAME)) {
RegionHandle = WalkRegion::Create(Region::RT_WALKREGION);
uint regionHandle = 0;
if (!strcmp(className, REGION_CLASS_NAME)) {
regionHandle = Region::create(Region::RT_REGION);
} else if (!strcmp(className, WALKREGION_CLASS_NAME)) {
regionHandle = WalkRegion::create(Region::RT_WALKREGION);
} else {
BS_ASSERT(false);
}
BS_ASSERT(RegionHandle);
BS_ASSERT(regionHandle);
// If the first element of the parameter is a number, then case 1 is accepted
// If the first element of the parameter is a table, then case 2 is accepted
// If the first element of the parameter has a different type, there is an error
lua_rawgeti(L, -1, 1);
int FirstElementType = lua_type(L, -1);
int firstElementType = lua_type(L, -1);
lua_pop(L, 1);
switch (FirstElementType) {
switch (firstElementType) {
case LUA_TNUMBER: {
Polygon polygon;
TablePolygonToPolygon(L, polygon);
RegionRegistry::GetInstance().resolveHandle(RegionHandle)->Init(polygon);
tablePolygonToPolygon(L, polygon);
RegionRegistry::getInstance().resolveHandle(regionHandle)->init(polygon);
}
break;
case LUA_TTABLE: {
lua_rawgeti(L, -1, 1);
Polygon polygon;
TablePolygonToPolygon(L, polygon);
tablePolygonToPolygon(L, polygon);
lua_pop(L, 1);
int PolygonCount = luaL_getn(L, -1);
if (PolygonCount == 1)
RegionRegistry::GetInstance().resolveHandle(RegionHandle)->Init(polygon);
int polygonCount = luaL_getn(L, -1);
if (polygonCount == 1)
RegionRegistry::getInstance().resolveHandle(regionHandle)->init(polygon);
else {
Common::Array<Polygon> Holes;
Holes.reserve(PolygonCount - 1);
Common::Array<Polygon> holes;
holes.reserve(polygonCount - 1);
for (int i = 2; i <= PolygonCount; i++) {
for (int i = 2; i <= polygonCount; i++) {
lua_rawgeti(L, -1, i);
Holes.resize(Holes.size() + 1);
TablePolygonToPolygon(L, Holes.back());
holes.resize(holes.size() + 1);
tablePolygonToPolygon(L, holes.back());
lua_pop(L, 1);
}
BS_ASSERT((int)Holes.size() == PolygonCount - 1);
BS_ASSERT((int)holes.size() == polygonCount - 1);
RegionRegistry::GetInstance().resolveHandle(RegionHandle)->Init(polygon, &Holes);
RegionRegistry::getInstance().resolveHandle(regionHandle)->init(polygon, &holes);
}
}
break;
@ -260,56 +244,46 @@ static uint TableRegionToRegion(lua_State *L, const char *ClassName) {
BS_ASSERT(__startStackDepth == lua_gettop(L));
#endif
return RegionHandle;
return regionHandle;
}
// -----------------------------------------------------------------------------
static void NewUserdataRegion(lua_State *L, const char *ClassName) {
static void newUserdataRegion(lua_State *L, const char *className) {
// Region due to the Lua code to create
// Any errors that occur will be intercepted to the luaL_error
uint RegionHandle = TableRegionToRegion(L, ClassName);
BS_ASSERT(RegionHandle);
uint regionHandle = tableRegionToRegion(L, className);
BS_ASSERT(regionHandle);
NewUintUserData(L, RegionHandle);
// luaL_getmetatable(L, ClassName);
LuaBindhelper::getMetatable(L, ClassName);
newUintUserData(L, regionHandle);
// luaL_getmetatable(L, className);
LuaBindhelper::getMetatable(L, className);
BS_ASSERT(!lua_isnil(L, -1));
lua_setmetatable(L, -2);
}
// -----------------------------------------------------------------------------
static int NewRegion(lua_State *L) {
NewUserdataRegion(L, REGION_CLASS_NAME);
static int newRegion(lua_State *L) {
newUserdataRegion(L, REGION_CLASS_NAME);
return 1;
}
// -----------------------------------------------------------------------------
static int NewWalkRegion(lua_State *L) {
NewUserdataRegion(L, WALKREGION_CLASS_NAME);
static int newWalkRegion(lua_State *L) {
newUserdataRegion(L, WALKREGION_CLASS_NAME);
return 1;
}
// -----------------------------------------------------------------------------
static const char *GEO_LIBRARY_NAME = "Geo";
static const luaL_reg GEO_FUNCTIONS[] = {
{"NewRegion", NewRegion},
{"NewWalkRegion", NewWalkRegion},
{"NewRegion", newRegion},
{"NewWalkRegion", newWalkRegion},
{0, 0}
};
// -----------------------------------------------------------------------------
static Region *CheckRegion(lua_State *L) {
static Region *checkRegion(lua_State *L) {
// The first parameter must be of type 'userdata', and the Metatable class Geo.Region or Geo.WalkRegion
uint *RegionHandlePtr;
if ((RegionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, REGION_CLASS_NAME))) != 0 ||
(RegionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
return RegionRegistry::GetInstance().resolveHandle(*RegionHandlePtr);
uint *regionHandlePtr;
if ((regionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, REGION_CLASS_NAME))) != 0 ||
(regionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
return RegionRegistry::getInstance().resolveHandle(*regionHandlePtr);
} else {
luaL_argcheck(L, 0, 1, "'" REGION_CLASS_NAME "' expected");
}
@ -318,181 +292,151 @@ static Region *CheckRegion(lua_State *L) {
return 0;
}
// -----------------------------------------------------------------------------
static int R_IsValid(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_isValid(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
lua_pushbooleancpp(L, pR->IsValid());
lua_pushbooleancpp(L, pR->isValid());
return 1;
}
// -----------------------------------------------------------------------------
static int R_GetX(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_getX(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
lua_pushnumber(L, pR->GetPosX());
lua_pushnumber(L, pR->getPosX());
return 1;
}
// -----------------------------------------------------------------------------
static int R_GetY(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_getY(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
lua_pushnumber(L, pR->GetPosY());
lua_pushnumber(L, pR->getPosY());
return 1;
}
// -----------------------------------------------------------------------------
static int R_GetPos(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_getPos(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
Vertex::VertexToLuaVertex(L, pR->GetPosition());
Vertex::vertexToLuaVertex(L, pR->getPosition());
return 1;
}
// -----------------------------------------------------------------------------
static int R_IsPointInRegion(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_isPointInRegion(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
Vertex Vertex;
Vertex::LuaVertexToVertex(L, 2, Vertex);
lua_pushbooleancpp(L, pR->IsPointInRegion(Vertex));
Vertex vertex;
Vertex::luaVertexToVertex(L, 2, vertex);
lua_pushbooleancpp(L, pR->isPointInRegion(vertex));
return 1;
}
// -----------------------------------------------------------------------------
static int R_SetPos(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_setPos(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
Vertex Vertex;
Vertex::LuaVertexToVertex(L, 2, Vertex);
pR->SetPos(Vertex.X, Vertex.Y);
Vertex vertex;
Vertex::luaVertexToVertex(L, 2, vertex);
pR->setPos(vertex.x, vertex.y);
return 0;
}
// -----------------------------------------------------------------------------
static int R_SetX(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_setX(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
pR->SetPosX(static_cast<int>(luaL_checknumber(L, 2)));
pR->setPosX(static_cast<int>(luaL_checknumber(L, 2)));
return 0;
}
// -----------------------------------------------------------------------------
static int R_SetY(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_setY(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
pR->SetPosY(static_cast<int>(luaL_checknumber(L, 2)));
pR->setPosY(static_cast<int>(luaL_checknumber(L, 2)));
return 0;
}
// -----------------------------------------------------------------------------
static void DrawPolygon(const Polygon &Polygon, uint Color, const Vertex &Offset) {
static void drawPolygon(const Polygon &polygon, uint color, const Vertex &offset) {
GraphicEngine *pGE = static_cast<GraphicEngine *>(Kernel::GetInstance()->GetService("gfx"));
BS_ASSERT(pGE);
for (int i = 0; i < Polygon.VertexCount - 1; i++)
pGE->DrawDebugLine(Polygon.Vertecies[i] + Offset, Polygon.Vertecies[i + 1] + Offset, Color);
for (int i = 0; i < polygon.vertexCount - 1; i++)
pGE->DrawDebugLine(polygon.vertices[i] + offset, polygon.vertices[i + 1] + offset, color);
pGE->DrawDebugLine(Polygon.Vertecies[Polygon.VertexCount - 1] + Offset, Polygon.Vertecies[0] + Offset, Color);
pGE->DrawDebugLine(polygon.vertices[polygon.vertexCount - 1] + offset, polygon.vertices[0] + offset, color);
}
// -----------------------------------------------------------------------------
static void DrawRegion(const Region &Region, uint Color, const Vertex &Offset) {
DrawPolygon(Region.GetContour(), Color, Offset);
for (int i = 0; i < Region.GetHoleCount(); i++)
DrawPolygon(Region.GetHole(i), Color, Offset);
static void drawRegion(const Region &region, uint color, const Vertex &offset) {
drawPolygon(region.getContour(), color, offset);
for (int i = 0; i < region.getHoleCount(); i++)
drawPolygon(region.getHole(i), color, offset);
}
// -----------------------------------------------------------------------------
static int R_Draw(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_draw(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
switch (lua_gettop(L)) {
case 3: {
Vertex Offset;
Vertex::LuaVertexToVertex(L, 3, Offset);
DrawRegion(*pR, GraphicEngine::LuaColorToARGBColor(L, 2), Offset);
Vertex offset;
Vertex::luaVertexToVertex(L, 3, offset);
drawRegion(*pR, GraphicEngine::LuaColorToARGBColor(L, 2), offset);
}
break;
case 2:
DrawRegion(*pR, GraphicEngine::LuaColorToARGBColor(L, 2), Vertex(0, 0));
drawRegion(*pR, GraphicEngine::LuaColorToARGBColor(L, 2), Vertex(0, 0));
break;
default:
DrawRegion(*pR, BS_RGB(255, 255, 255), Vertex(0, 0));
drawRegion(*pR, BS_RGB(255, 255, 255), Vertex(0, 0));
}
return 0;
}
// -----------------------------------------------------------------------------
static int R_GetCentroid(lua_State *L) {
Region *RPtr = CheckRegion(L);
static int r_getCentroid(lua_State *L) {
Region *RPtr = checkRegion(L);
BS_ASSERT(RPtr);
Vertex::VertexToLuaVertex(L, RPtr->GetCentroid());
Vertex::vertexToLuaVertex(L, RPtr->getCentroid());
return 1;
}
// -----------------------------------------------------------------------------
static int R_Delete(lua_State *L) {
Region *pR = CheckRegion(L);
static int r_delete(lua_State *L) {
Region *pR = checkRegion(L);
BS_ASSERT(pR);
delete pR;
return 0;
}
// -----------------------------------------------------------------------------
static const luaL_reg REGION_METHODS[] = {
{"SetPos", R_SetPos},
{"SetX", R_SetX},
{"SetY", R_SetY},
{"GetPos", R_GetPos},
{"IsPointInRegion", R_IsPointInRegion},
{"GetX", R_GetX},
{"GetY", R_GetY},
{"IsValid", R_IsValid},
{"Draw", R_Draw},
{"GetCentroid", R_GetCentroid},
{"SetPos", r_setPos},
{"SetX", r_setX},
{"SetY", r_setY},
{"GetPos", r_getPos},
{"IsPointInRegion", r_isPointInRegion},
{"GetX", r_getX},
{"GetY", r_getY},
{"IsValid", r_isValid},
{"Draw", r_draw},
{"GetCentroid", r_getCentroid},
{0, 0}
};
// -----------------------------------------------------------------------------
static WalkRegion *CheckWalkRegion(lua_State *L) {
static WalkRegion *checkWalkRegion(lua_State *L) {
// The first parameter must be of type 'userdate', and the Metatable class Geo.WalkRegion
uint RegionHandle;
if ((RegionHandle = *reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
return reinterpret_cast<WalkRegion *>(RegionRegistry::GetInstance().resolveHandle(RegionHandle));
uint regionHandle;
if ((regionHandle = *reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) {
return reinterpret_cast<WalkRegion *>(RegionRegistry::getInstance().resolveHandle(regionHandle));
} else {
luaL_argcheck(L, 0, 1, "'" WALKREGION_CLASS_NAME "' expected");
}
@ -501,23 +445,21 @@ static WalkRegion *CheckWalkRegion(lua_State *L) {
return 0;
}
// -----------------------------------------------------------------------------
static int WR_GetPath(lua_State *L) {
WalkRegion *pWR = CheckWalkRegion(L);
static int wr_getPath(lua_State *L) {
WalkRegion *pWR = checkWalkRegion(L);
BS_ASSERT(pWR);
Vertex Start;
Vertex::LuaVertexToVertex(L, 2, Start);
Vertex End;
Vertex::LuaVertexToVertex(L, 3, End);
BS_Path Path;
if (pWR->QueryPath(Start, End, Path)) {
Vertex start;
Vertex::luaVertexToVertex(L, 2, start);
Vertex end;
Vertex::luaVertexToVertex(L, 3, end);
BS_Path path;
if (pWR->queryPath(start, end, path)) {
lua_newtable(L);
BS_Path::const_iterator it = Path.begin();
for (; it != Path.end(); it++) {
lua_pushnumber(L, (it - Path.begin()) + 1);
Vertex::VertexToLuaVertex(L, *it);
BS_Path::const_iterator it = path.begin();
for (; it != path.end(); it++) {
lua_pushnumber(L, (it - path.begin()) + 1);
Vertex::vertexToLuaVertex(L, *it);
lua_settable(L, -3);
}
} else
@ -526,16 +468,12 @@ static int WR_GetPath(lua_State *L) {
return 1;
}
// -----------------------------------------------------------------------------
static const luaL_reg WALKREGION_METHODS[] = {
{"GetPath", WR_GetPath},
{"GetPath", wr_getPath},
{0, 0}
};
// -----------------------------------------------------------------------------
bool Geometry::_RegisterScriptBindings() {
bool Geometry::registerScriptBindings() {
Kernel *pKernel = Kernel::GetInstance();
BS_ASSERT(pKernel);
ScriptEngine *pScript = static_cast<ScriptEngine *>(pKernel->GetService("script"));
@ -547,8 +485,8 @@ bool Geometry::_RegisterScriptBindings() {
if (!LuaBindhelper::addMethodsToClass(L, WALKREGION_CLASS_NAME, REGION_METHODS)) return false;
if (!LuaBindhelper::addMethodsToClass(L, WALKREGION_CLASS_NAME, WALKREGION_METHODS)) return false;
if (!LuaBindhelper::setClassGCHandler(L, REGION_CLASS_NAME, R_Delete)) return false;
if (!LuaBindhelper::setClassGCHandler(L, WALKREGION_CLASS_NAME, R_Delete)) return false;
if (!LuaBindhelper::setClassGCHandler(L, REGION_CLASS_NAME, r_delete)) return false;
if (!LuaBindhelper::setClassGCHandler(L, WALKREGION_CLASS_NAME, r_delete)) return false;
if (!LuaBindhelper::addFunctionsToLib(L, GEO_LIBRARY_NAME, GEO_FUNCTIONS)) return false;

View File

@ -47,14 +47,8 @@
#ifndef SWORD25_LINE_H
#define SWORD25_LINE_H
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include "sword25/kernel/common.h"
// -----------------------------------------------------------------------------
namespace Sword25 {
class Line {
@ -67,12 +61,12 @@ public:
* @return Returns true if the point is to the left of the line.
* If the point is to the right of the line or on the line, false is returned.
*/
static bool IsVertexLeft(const Vertex &a, const Vertex &b, const Vertex &c) {
return _TriangleArea2(a, b, c) > 0;
static bool isVertexLeft(const Vertex &a, const Vertex &b, const Vertex &c) {
return triangleArea2(a, b, c) > 0;
}
static bool IsVertexLeftOn(const Vertex &a, const Vertex &b, const Vertex &c) {
return _TriangleArea2(a, b, c) >= 0;
static bool isVertexLeftOn(const Vertex &a, const Vertex &b, const Vertex &c) {
return triangleArea2(a, b, c) >= 0;
}
/**
@ -83,12 +77,12 @@ public:
* @return Returns true if the point is to the right of the line.
* If the point is to the right of the line or on the line, false is returned.
*/
static bool IsVertexRight(const Vertex &a, const Vertex &b, const Vertex &c) {
return _TriangleArea2(a, b, c) < 0;
static bool isVertexRight(const Vertex &a, const Vertex &b, const Vertex &c) {
return triangleArea2(a, b, c) < 0;
}
static bool IsVertexRightOn(const Vertex &a, const Vertex &b, const Vertex &c) {
return _TriangleArea2(a, b, c) <= 0;
static bool isVertexRightOn(const Vertex &a, const Vertex &b, const Vertex &c) {
return triangleArea2(a, b, c) <= 0;
}
/**
@ -98,8 +92,8 @@ public:
* @param c The test point
* @return Returns true if the point is on the line, false otherwise.
*/
static bool IsVertexOn(const Vertex &a, const Vertex &b, const Vertex &c) {
return _TriangleArea2(a, b, c) == 0;
static bool isVertexOn(const Vertex &a, const Vertex &b, const Vertex &c) {
return triangleArea2(a, b, c) == 0;
}
enum VERTEX_CLASSIFICATION {
@ -117,10 +111,10 @@ public:
* RIGHT is returned if the point is to the right of the line.
* ON is returned if the point is on the line.
*/
static VERTEX_CLASSIFICATION ClassifyVertexToLine(const Vertex &a, const Vertex &b, const Vertex &c) {
int Area = _TriangleArea2(a, b, c);
if (Area > 0) return LEFT;
if (Area < 0) return RIGHT;
static VERTEX_CLASSIFICATION classifyVertexToLine(const Vertex &a, const Vertex &b, const Vertex &c) {
int area = triangleArea2(a, b, c);
if (area > 0) return LEFT;
if (area < 0) return RIGHT;
return ON;
}
@ -132,15 +126,15 @@ public:
* @param d The end point of the second line
* @remark In cases where a line only touches the other, false is returned (improper intersection)
*/
static bool DoesIntersectProperly(const Vertex &a, const Vertex &b, const Vertex &c, const Vertex &d) {
VERTEX_CLASSIFICATION Class1 = ClassifyVertexToLine(a, b, c);
VERTEX_CLASSIFICATION Class2 = ClassifyVertexToLine(a, b, d);
VERTEX_CLASSIFICATION Class3 = ClassifyVertexToLine(c, d, a);
VERTEX_CLASSIFICATION Class4 = ClassifyVertexToLine(c, d, b);
static bool doesIntersectProperly(const Vertex &a, const Vertex &b, const Vertex &c, const Vertex &d) {
VERTEX_CLASSIFICATION class1 = classifyVertexToLine(a, b, c);
VERTEX_CLASSIFICATION class2 = classifyVertexToLine(a, b, d);
VERTEX_CLASSIFICATION class3 = classifyVertexToLine(c, d, a);
VERTEX_CLASSIFICATION class4 = classifyVertexToLine(c, d, b);
if (Class1 == ON || Class2 == ON || Class3 == ON || Class4 == ON) return false;
if (class1 == ON || class2 == ON || class3 == ON || class4 == ON) return false;
return ((Class1 == LEFT) ^(Class2 == LEFT)) && ((Class3 == LEFT) ^(Class4 == LEFT));
return ((class1 == LEFT) ^(class2 == LEFT)) && ((class3 == LEFT) ^(class4 == LEFT));
}
/**
@ -149,39 +143,39 @@ public:
* @param b The end point of a line
* @param c The test point
*/
static bool IsOnLine(const Vertex &a, const Vertex &b, const Vertex &c) {
static bool isOnLine(const Vertex &a, const Vertex &b, const Vertex &c) {
// The items must all be Collinear, otherwise don't bothering testing the point
if (_TriangleArea2(a, b, c) != 0) return false;
if (triangleArea2(a, b, c) != 0) return false;
// If the line segment is not vertical, check on the x-axis, otherwise the y-axis
if (a.X != b.X) {
return ((a.X <= c.X) &&
(c.X <= b.X)) ||
((a.X >= c.X) &&
(c.X >= b.X));
if (a.x != b.x) {
return ((a.x <= c.x) &&
(c.x <= b.x)) ||
((a.x >= c.x) &&
(c.x >= b.x));
} else {
return ((a.Y <= c.Y) &&
(c.Y <= b.Y)) ||
((a.Y >= c.Y) &&
(c.Y >= b.Y));
return ((a.y <= c.y) &&
(c.y <= b.y)) ||
((a.y >= c.y) &&
(c.y >= b.y));
}
}
static bool IsOnLineStrict(const Vertex &a, const Vertex &b, const Vertex &c) {
static bool isOnLineStrict(const Vertex &a, const Vertex &b, const Vertex &c) {
// The items must all be Collinear, otherwise don't bothering testing the point
if (_TriangleArea2(a, b, c) != 0) return false;
if (triangleArea2(a, b, c) != 0) return false;
// If the line segment is not vertical, check on the x-axis, otherwise the y-axis
if (a.X != b.X) {
return ((a.X < c.X) &&
(c.X < b.X)) ||
((a.X > c.X) &&
(c.X > b.X));
if (a.x != b.x) {
return ((a.x < c.x) &&
(c.x < b.x)) ||
((a.x > c.x) &&
(c.x > b.x));
} else {
return ((a.Y < c.Y) &&
(c.Y < b.Y)) ||
((a.Y > c.Y) &&
(c.Y > b.Y));
return ((a.y < c.y) &&
(c.y < b.y)) ||
((a.y > c.y) &&
(c.y > b.y));
}
}
@ -192,10 +186,10 @@ private:
* The result is positive if the points are arrange counterclockwise,
* and negative if they are arranged counter-clockwise.
*/
static int _TriangleArea2(const Vertex &a, const Vertex &b, const Vertex &c) {
return a.X * b.Y - a.Y * b.X +
a.Y * c.X - a.X * c.Y +
b.X * c.Y - c.X * b.Y;
static int triangleArea2(const Vertex &a, const Vertex &b, const Vertex &c) {
return a.x * b.y - a.y * b.x +
a.y * c.x - a.x * c.y +
b.x * c.y - c.x * b.y;
}
};

View File

@ -42,114 +42,107 @@
namespace Sword25 {
#define max(a,b) (((a) > (b)) ? (a) : (b))
// Constructor / Destructor
// --------------------------
Polygon::Polygon() : VertexCount(0), Vertecies(NULL) {
Polygon::Polygon() : vertexCount(0), vertices(NULL) {
}
Polygon::Polygon(int VertexCount_, const Vertex *Vertecies_) : VertexCount(0), Vertecies(NULL) {
Init(VertexCount_, Vertecies_);
Polygon::Polygon(int vertexCount_, const Vertex *vertices_) : vertexCount(0), vertices(NULL) {
init(vertexCount_, vertices_);
}
Polygon::Polygon(const Polygon &Other) : VertexCount(0), Vertecies(NULL) {
Init(Other.VertexCount, Other.Vertecies);
Polygon::Polygon(const Polygon &other) : vertexCount(0), vertices(NULL) {
init(other.vertexCount, other.vertices);
}
Polygon::Polygon(InputPersistenceBlock &Reader) : VertexCount(0), Vertecies(NULL) {
Polygon::Polygon(InputPersistenceBlock &Reader) : vertexCount(0), vertices(NULL) {
unpersist(Reader);
}
Polygon::~Polygon() {
delete[] Vertecies;
delete[] vertices;
}
// Initialisation
// ---------------
bool Polygon::Init(int VertexCount_, const Vertex *Vertecies_) {
bool Polygon::init(int vertexCount_, const Vertex *vertices_) {
// Rember the old obstate to restore it if an error occurs whilst initialising it with the new data
int OldVertexCount = this->VertexCount;
Vertex *OldVertecies = this->Vertecies;
int oldvertexCount = this->vertexCount;
Vertex *oldvertices = this->vertices;
this->VertexCount = VertexCount_;
this->Vertecies = new Vertex[VertexCount_ + 1];
memcpy(this->Vertecies, Vertecies_, sizeof(Vertex) * VertexCount_);
this->vertexCount = vertexCount_;
this->vertices = new Vertex[vertexCount_ + 1];
memcpy(this->vertices, vertices_, sizeof(Vertex) * vertexCount_);
// TODO:
// Duplicate and remove redundant vertecies (Superflous = 3 co-linear verts)
// _WeedRepeatedVertecies();
// _WeedRepeatedvertices();
// The first vertex is repeated at the end of the vertex array; this simplifies
// some algorithms, running through the edges and thus can save the overflow control.
this->Vertecies[VertexCount_] = this->Vertecies[0];
this->vertices[vertexCount_] = this->vertices[0];
// If the polygon is self-intersecting, the object state is restore, and an error signalled
if (CheckForSelfIntersection()) {
delete[] this->Vertecies;
this->Vertecies = OldVertecies;
this->VertexCount = OldVertexCount;
if (checkForSelfIntersection()) {
delete[] this->vertices;
this->vertices = oldvertices;
this->vertexCount = oldvertexCount;
// BS_LOG_ERROR("POLYGON: Tried to create a self-intersecting polygon.\n");
return false;
}
// Release old vertex list
delete[] OldVertecies;
delete[] oldvertices;
// Calculate properties of the polygon
m_IsCW = ComputeIsCW();
m_IsConvex = ComputeIsConvex();
m_Centroid = ComputeCentroid();
_isCW = computeIsCW();
_isConvex = computeIsConvex();
_centroid = computeCentroid();
return true;
}
// Review the order of the Vertecies
// Review the order of the vertices
// ---------------------------------
bool Polygon::IsCW() const {
return m_IsCW;
bool Polygon::isCW() const {
return _isCW;
}
bool Polygon::IsCCW() const {
return !IsCW();
bool Polygon::isCCW() const {
return !isCW();
}
bool Polygon::ComputeIsCW() const {
if (VertexCount) {
bool Polygon::computeIsCW() const {
if (vertexCount) {
// Find the vertex on extreme bottom right
int V2Index = FindLRVertexIndex();
int v2Index = findLRVertexIndex();
// Find the vertex before and after it
int V1Index = (V2Index + (VertexCount - 1)) % VertexCount;
int V3Index = (V2Index + 1) % VertexCount;
int v1Index = (v2Index + (vertexCount - 1)) % vertexCount;
int v3Index = (v2Index + 1) % vertexCount;
// Cross product form
// If the cross product of the vertex lying fartherest bottom left is positive,
// the vertecies arrranged in a clockwise order. Otherwise counter-clockwise
if (CrossProduct(Vertecies[V1Index], Vertecies[V2Index], Vertecies[V3Index]) >= 0) return true;
if (crossProduct(vertices[v1Index], vertices[v2Index], vertices[v3Index]) >= 0)
return true;
}
return false;
}
int Polygon::FindLRVertexIndex() const {
if (VertexCount) {
int CurIndex = 0;
int MaxX = Vertecies[0].X;
int MaxY = Vertecies[0].Y;
int Polygon::findLRVertexIndex() const {
if (vertexCount) {
int curIndex = 0;
int maxX = vertices[0].x;
int maxY = vertices[0].y;
for (int i = 1; i < VertexCount; i++) {
if (Vertecies[i].Y > MaxY ||
(Vertecies[i].Y == MaxY && Vertecies[i].X > MaxX)) {
MaxX = Vertecies[i].X;
MaxY = Vertecies[i].Y;
CurIndex = i;
for (int i = 1; i < vertexCount; i++) {
if (vertices[i].y > maxY ||
(vertices[i].y == maxY && vertices[i].x > maxX)) {
maxX = vertices[i].x;
maxY = vertices[i].y;
curIndex = i;
}
}
return CurIndex;
return curIndex;
}
return -1;
@ -158,40 +151,41 @@ int Polygon::FindLRVertexIndex() const {
// Testing for Convex / Concave
// ------------------------
bool Polygon::IsConvex() const {
return m_IsConvex;
bool Polygon::isConvex() const {
return _isConvex;
}
bool Polygon::IsConcave() const {
return !IsConvex();
bool Polygon::isConcave() const {
return !isConvex();
}
bool Polygon::ComputeIsConvex() const {
// Polygons with three or less Vertecies can only be convex
if (VertexCount <= 3) return true;
bool Polygon::computeIsConvex() const {
// Polygons with three or less vertices can only be convex
if (vertexCount <= 3) return true;
// All angles in the polygon computed will have the same direction sign if the polygon is convex
int Flag = 0;
for (int i = 0; i < VertexCount; i++) {
int flag = 0;
for (int i = 0; i < vertexCount; i++) {
// Determine the next two vertecies to check
int j = (i + 1) % VertexCount;
int k = (i + 2) % VertexCount;
int j = (i + 1) % vertexCount;
int k = (i + 2) % vertexCount;
// Calculate the cross product of the three vertecies
int Cross = CrossProduct(Vertecies[i], Vertecies[j], Vertecies[k]);
int cross = crossProduct(vertices[i], vertices[j], vertices[k]);
// The lower two bits of the flag represent the following:
// 0: negative angle occurred
// 1: positive angle occurred
// The sign of the current angle is recorded in Flag
if (Cross < 0)
Flag |= 1;
else if (Cross > 0)
Flag |= 2;
if (cross < 0)
flag |= 1;
else if (cross > 0)
flag |= 2;
// If flag is 3, there are both positive and negative angles; so the polygon is concave
if (Flag == 3) return false;
if (flag == 3)
return false;
}
// Polygon is convex
@ -201,65 +195,65 @@ bool Polygon::ComputeIsConvex() const {
// Make a determine vertex order
// -----------------------------
void Polygon::EnsureCWOrder() {
if (!IsCW())
ReverseVertexOrder();
void Polygon::ensureCWOrder() {
if (!isCW())
reverseVertexOrder();
}
void Polygon::EnsureCCWOrder() {
if (!IsCCW())
ReverseVertexOrder();
void Polygon::ensureCCWOrder() {
if (!isCCW())
reverseVertexOrder();
}
// Reverse the order of vertecies
// ------------------------------
void Polygon::ReverseVertexOrder() {
// Vertecies are exchanged in pairs, until the list has been completely reversed
for (int i = 0; i < VertexCount / 2; i++) {
Vertex tempVertex = Vertecies[i];
Vertecies[i] = Vertecies[VertexCount - i - 1];
Vertecies[VertexCount - i - 1] = tempVertex;
void Polygon::reverseVertexOrder() {
// vertices are exchanged in pairs, until the list has been completely reversed
for (int i = 0; i < vertexCount / 2; i++) {
Vertex tempVertex = vertices[i];
vertices[i] = vertices[vertexCount - i - 1];
vertices[vertexCount - i - 1] = tempVertex;
}
// Vertexordnung neu berechnen.
m_IsCW = ComputeIsCW();
_isCW = computeIsCW();
}
// Cross Product
// -------------
int Polygon::CrossProduct(const Vertex &V1, const Vertex &V2, const Vertex &V3) const {
return (V2.X - V1.X) * (V3.Y - V2.Y) -
(V2.Y - V1.Y) * (V3.X - V2.X);
int Polygon::crossProduct(const Vertex &v1, const Vertex &v2, const Vertex &v3) const {
return (v2.x - v1.x) * (v3.y - v2.y) -
(v2.y - v1.y) * (v3.x - v2.x);
}
// Scalar Product
// --------------
int Polygon::DotProduct(const Vertex &V1, const Vertex &V2, const Vertex &V3) const {
return (V1.X - V2.X) * (V3.X - V2.X) +
(V1.Y - V2.Y) * (V3.X - V2.Y);
int Polygon::dotProduct(const Vertex &v1, const Vertex &v2, const Vertex &v3) const {
return (v1.x - v2.x) * (v3.x - v2.x) +
(v1.y - v2.y) * (v3.x - v2.y);
}
// Check for self-intersections
// ----------------------------
bool Polygon::CheckForSelfIntersection() const {
bool Polygon::checkForSelfIntersection() const {
// TODO: Finish this
/*
float AngleSum = 0.0f;
for (int i = 0; i < VertexCount; i++) {
int j = (i + 1) % VertexCount;
int k = (i + 2) % VertexCount;
for (int i = 0; i < vertexCount; i++) {
int j = (i + 1) % vertexCount;
int k = (i + 2) % vertexCount;
float Dot = DotProduct(Vertecies[i], Vertecies[j], Vertecies[k]);
float Dot = DotProduct(vertices[i], vertices[j], vertices[k]);
// Skalarproduct normalisieren
float Length1 = sqrt((Vertecies[i].X - Vertecies[j].X) * (Vertecies[i].X - Vertecies[j].X) +
(Vertecies[i].Y - Vertecies[j].Y) * (Vertecies[i].Y - Vertecies[j].Y));
float Length2 = sqrt((Vertecies[k].X - Vertecies[j].X) * (Vertecies[k].X - Vertecies[j].X) +
(Vertecies[k].Y - Vertecies[j].Y) * (Vertecies[k].Y - Vertecies[j].Y));
float Length1 = sqrt((vertices[i].x - vertices[j].x) * (vertices[i].x - vertices[j].x) +
(vertices[i].y - vertices[j].y) * (vertices[i].y - vertices[j].y));
float Length2 = sqrt((vertices[k].x - vertices[j].x) * (vertices[k].x - vertices[j].x) +
(vertices[k].y - vertices[j].y) * (vertices[k].y - vertices[j].y));
float Norm = Length1 * Length2;
if (Norm > 0.0f) {
@ -275,168 +269,190 @@ bool Polygon::CheckForSelfIntersection() const {
// Move
// ----
void Polygon::operator+=(const Vertex &Delta) {
void Polygon::operator+=(const Vertex &delta) {
// Move all vertecies
for (int i = 0; i < VertexCount; i++)
Vertecies[i] += Delta;
for (int i = 0; i < vertexCount; i++)
vertices[i] += delta;
// Shift the focus
m_Centroid += Delta;
_centroid += delta;
}
// Line of Sight
// -------------
bool Polygon::IsLineInterior(const Vertex &a, const Vertex &b) const {
bool Polygon::isLineInterior(const Vertex &a, const Vertex &b) const {
// Both points have to be in the polygon
if (!IsPointInPolygon(a, true) || !IsPointInPolygon(b, true)) return false;
if (!isPointInPolygon(a, true) || !isPointInPolygon(b, true))
return false;
// If the points are identical, the line is trivially within the polygon
if (a == b) return true;
if (a == b)
return true;
// Test whether the line intersects a line segment strictly (proper intersection)
for (int i = 0; i < VertexCount; i++) {
int j = (i + 1) % VertexCount;
const Vertex &VS = Vertecies[i];
const Vertex &VE = Vertecies[j];
for (int i = 0; i < vertexCount; i++) {
int j = (i + 1) % vertexCount;
const Vertex &vs = vertices[i];
const Vertex &ve = vertices[j];
// If the line intersects a line segment strictly (proper cross section) the line is not in the polygon
if (Line::DoesIntersectProperly(a, b, VS, VE)) return false;
if (Line::doesIntersectProperly(a, b, vs, ve))
return false;
// If one of the two line items is on the edge and the other is to the right of the edge,
// then the line is not completely within the polygon
if (Line::IsOnLineStrict(VS, VE, a) && Line::IsVertexRight(VS, VE, b)) return false;
if (Line::IsOnLineStrict(VS, VE, b) && Line::IsVertexRight(VS, VE, a)) return false;
if (Line::isOnLineStrict(vs, ve, a) && Line::isVertexRight(vs, ve, b))
return false;
if (Line::isOnLineStrict(vs, ve, b) && Line::isVertexRight(vs, ve, a))
return false;
// If one of the two line items is on a vertex, the line traces into the polygon
if ((a == VS) && !IsLineInCone(i, b, true)) return false;
if ((b == VS) && !IsLineInCone(i, a, true)) return false;
if ((a == vs) && !isLineInCone(i, b, true))
return false;
if ((b == vs) && !isLineInCone(i, a, true))
return false;
}
return true;
}
bool Polygon::IsLineExterior(const Vertex &a, const Vertex &b) const {
bool Polygon::isLineExterior(const Vertex &a, const Vertex &b) const {
// Neither of the two points must be strictly in the polygon (on the edge is allowed)
if (IsPointInPolygon(a, false) || IsPointInPolygon(b, false)) return false;
if (isPointInPolygon(a, false) || isPointInPolygon(b, false))
return false;
// If the points are identical, the line is trivially outside of the polygon
if (a == b) return true;
if (a == b)
return true;
// Test whether the line intersects a line segment strictly (proper intersection)
for (int i = 0; i < VertexCount; i++) {
int j = (i + 1) % VertexCount;
const Vertex &VS = Vertecies[i];
const Vertex &VE = Vertecies[j];
for (int i = 0; i < vertexCount; i++) {
int j = (i + 1) % vertexCount;
const Vertex &vs = vertices[i];
const Vertex &ve = vertices[j];
// If the line intersects a line segment strictly (proper intersection), then
// the line is partially inside the polygon
if (Line::DoesIntersectProperly(a, b, VS, VE)) return false;
if (Line::doesIntersectProperly(a, b, vs, ve))
return false;
// If one of the two line items is on the edge and the other is to the right of the edge,
// the line is not completely outside the polygon
if (Line::IsOnLineStrict(VS, VE, a) && Line::IsVertexLeft(VS, VE, b)) return false;
if (Line::IsOnLineStrict(VS, VE, b) && Line::IsVertexLeft(VS, VE, a)) return false;
if (Line::isOnLineStrict(vs, ve, a) && Line::isVertexLeft(vs, ve, b))
return false;
if (Line::isOnLineStrict(vs, ve, b) && Line::isVertexLeft(vs, ve, a))
return false;
// If one of the lwo line items is on a vertex, the line must not run into the polygon
if ((a == VS) && IsLineInCone(i, b, false)) return false;
if ((b == VS) && IsLineInCone(i, a, false)) return false;
if ((a == vs) && isLineInCone(i, b, false))
return false;
if ((b == vs) && isLineInCone(i, a, false))
return false;
// If the vertex with start and end point is collinear, (a VS) and (b, VS) is not in the polygon
if (Line::IsOnLine(a, b, VS)) {
if (IsLineInCone(i, a, false)) return false;
if (IsLineInCone(i, b, false)) return false;
// If the vertex with start and end point is collinear, (a vs) and (b, vs) is not in the polygon
if (Line::isOnLine(a, b, vs)) {
if (isLineInCone(i, a, false))
return false;
if (isLineInCone(i, b, false))
return false;
}
}
return true;
}
bool Polygon::IsLineInCone(int StartVertexIndex, const Vertex &EndVertex, bool IncludeEdges) const {
const Vertex &StartVertex = Vertecies[StartVertexIndex];
const Vertex &NextVertex = Vertecies[(StartVertexIndex + 1) % VertexCount];
const Vertex &PrevVertex = Vertecies[(StartVertexIndex + VertexCount - 1) % VertexCount];
bool Polygon::isLineInCone(int startVertexIndex, const Vertex &endVertex, bool includeEdges) const {
const Vertex &startVertex = vertices[startVertexIndex];
const Vertex &nextVertex = vertices[(startVertexIndex + 1) % vertexCount];
const Vertex &prevVertex = vertices[(startVertexIndex + vertexCount - 1) % vertexCount];
if (Line::IsVertexLeftOn(PrevVertex, StartVertex, NextVertex)) {
if (IncludeEdges)
return Line::IsVertexLeftOn(EndVertex, StartVertex, NextVertex) &&
Line::IsVertexLeftOn(StartVertex, EndVertex, PrevVertex);
if (Line::isVertexLeftOn(prevVertex, startVertex, nextVertex)) {
if (includeEdges)
return Line::isVertexLeftOn(endVertex, startVertex, nextVertex) &&
Line::isVertexLeftOn(startVertex, endVertex, prevVertex);
else
return Line::IsVertexLeft(EndVertex, StartVertex, NextVertex) &&
Line::IsVertexLeft(StartVertex, EndVertex, PrevVertex);
return Line::isVertexLeft(endVertex, startVertex, nextVertex) &&
Line::isVertexLeft(startVertex, endVertex, prevVertex);
} else {
if (IncludeEdges)
return !(Line::IsVertexLeft(EndVertex, StartVertex, PrevVertex) &&
Line::IsVertexLeft(StartVertex, EndVertex, NextVertex));
if (includeEdges)
return !(Line::isVertexLeft(endVertex, startVertex, prevVertex) &&
Line::isVertexLeft(startVertex, endVertex, nextVertex));
else
return !(Line::IsVertexLeftOn(EndVertex, StartVertex, PrevVertex) &&
Line::IsVertexLeftOn(StartVertex, EndVertex, NextVertex));
return !(Line::isVertexLeftOn(endVertex, startVertex, prevVertex) &&
Line::isVertexLeftOn(startVertex, endVertex, nextVertex));
}
}
// Point-Polygon Tests
// -------------------
bool Polygon::IsPointInPolygon(int X, int Y, bool BorderBelongsToPolygon) const {
return IsPointInPolygon(Vertex(X, Y), BorderBelongsToPolygon);
bool Polygon::isPointInPolygon(int x, int y, bool borderBelongsToPolygon) const {
return isPointInPolygon(Vertex(x, y), borderBelongsToPolygon);
}
bool Polygon::IsPointInPolygon(const Vertex &Point, bool EdgesBelongToPolygon) const {
int Rcross = 0; // Number of right-side overlaps
int Lcross = 0; // Number of left-side overlaps
bool Polygon::isPointInPolygon(const Vertex &point, bool edgesBelongToPolygon) const {
int rcross = 0; // Number of right-side overlaps
int lcross = 0; // Number of left-side overlaps
// Each edge is checked whether it cuts the outgoing stream from the point
for (int i = 0; i < VertexCount; i++) {
const Vertex &EdgeStart = Vertecies[i];
const Vertex &EdgeEnd = Vertecies[(i + 1) % VertexCount];
for (int i = 0; i < vertexCount; i++) {
const Vertex &edgeStart = vertices[i];
const Vertex &edgeEnd = vertices[(i + 1) % vertexCount];
// A vertex is a point? Then it lies on one edge of the polygon
if (Point == EdgeStart) return EdgesBelongToPolygon;
if (point == edgeStart)
return edgesBelongToPolygon;
if ((EdgeStart.Y > Point.Y) != (EdgeEnd.Y > Point.Y)) {
int Term1 = (EdgeStart.X - Point.X) * (EdgeEnd.Y - Point.Y) - (EdgeEnd.X - Point.X) * (EdgeStart.Y - Point.Y);
int Term2 = (EdgeEnd.Y - Point.Y) - (EdgeStart.Y - EdgeEnd.Y);
if ((Term1 > 0) == (Term2 >= 0)) Rcross++;
if ((edgeStart.y > point.y) != (edgeEnd.y > point.y)) {
int term1 = (edgeStart.x - point.x) * (edgeEnd.y - point.y) - (edgeEnd.x - point.x) * (edgeStart.y - point.y);
int term2 = (edgeEnd.y - point.y) - (edgeStart.y - edgeEnd.y);
if ((term1 > 0) == (term2 >= 0))
rcross++;
}
if ((EdgeStart.Y < Point.Y) != (EdgeEnd.Y < Point.Y)) {
int Term1 = (EdgeStart.X - Point.X) * (EdgeEnd.Y - Point.Y) - (EdgeEnd.X - Point.X) * (EdgeStart.Y - Point.Y);
int Term2 = (EdgeEnd.Y - Point.Y) - (EdgeStart.Y - EdgeEnd.Y);
if ((Term1 < 0) == (Term2 <= 0)) Lcross++;
if ((edgeStart.y < point.y) != (edgeEnd.y < point.y)) {
int term1 = (edgeStart.x - point.x) * (edgeEnd.y - point.y) - (edgeEnd.x - point.x) * (edgeStart.y - point.y);
int term2 = (edgeEnd.y - point.y) - (edgeStart.y - edgeEnd.y);
if ((term1 < 0) == (term2 <= 0))
lcross++;
}
}
// The point is on an adge, if the number of left and right intersections have the same even numbers
if ((Rcross % 2) != (Lcross % 2)) return EdgesBelongToPolygon;
if ((rcross % 2) != (lcross % 2))
return edgesBelongToPolygon;
// The point is strictly inside the polygon if and only if the number of overlaps is odd
if ((Rcross % 2) == 1) return true;
else return false;
if ((rcross % 2) == 1)
return true;
else
return false;
}
bool Polygon::persist(OutputPersistenceBlock &writer) {
writer.write(VertexCount);
for (int i = 0; i < VertexCount; ++i) {
writer.write(Vertecies[i].X);
writer.write(Vertecies[i].Y);
writer.write(vertexCount);
for (int i = 0; i < vertexCount; ++i) {
writer.write(vertices[i].x);
writer.write(vertices[i].y);
}
return true;
}
bool Polygon::unpersist(InputPersistenceBlock &reader) {
int StoredVertexCount;
reader.read(StoredVertexCount);
int storedvertexCount;
reader.read(storedvertexCount);
Common::Array<Vertex> StoredVertecies;
for (int i = 0; i < StoredVertexCount; ++i) {
Common::Array<Vertex> storedvertices;
for (int i = 0; i < storedvertexCount; ++i) {
int x, y;
reader.read(x);
reader.read(y);
StoredVertecies.push_back(Vertex(x, y));
storedvertices.push_back(Vertex(x, y));
}
Init(StoredVertexCount, &StoredVertecies[0]);
init(storedvertexCount, &storedvertices[0]);
return reader.isGood();
}
@ -444,31 +460,32 @@ bool Polygon::unpersist(InputPersistenceBlock &reader) {
// Main Focus
// ----------
Vertex Polygon::GetCentroid() const {
return m_Centroid;
Vertex Polygon::getCentroid() const {
return _centroid;
}
Vertex Polygon::ComputeCentroid() const {
Vertex Polygon::computeCentroid() const {
// Area of the polygon is calculated
int DoubleArea = 0;
for (int i = 0; i < VertexCount; ++i) {
DoubleArea += Vertecies[i].X * Vertecies[i + 1].Y - Vertecies[i + 1].X * Vertecies[i].Y;
int doubleArea = 0;
for (int i = 0; i < vertexCount; ++i) {
doubleArea += vertices[i].x * vertices[i + 1].y - vertices[i + 1].x * vertices[i].y;
}
// Avoid division by zero in the next step
if (DoubleArea == 0) return Vertex();
if (doubleArea == 0)
return Vertex();
// Calculate centroid
Vertex Centroid;
for (int i = 0; i < VertexCount; ++i) {
int Area = Vertecies[i].X * Vertecies[i + 1].Y - Vertecies[i + 1].X * Vertecies[i].Y;
Centroid.X += (Vertecies[i].X + Vertecies[i + 1].X) * Area;
Centroid.Y += (Vertecies[i].Y + Vertecies[i + 1].Y) * Area;
Vertex centroid;
for (int i = 0; i < vertexCount; ++i) {
int area = vertices[i].x * vertices[i + 1].y - vertices[i + 1].x * vertices[i].y;
centroid.x += (vertices[i].x + vertices[i + 1].x) * area;
centroid.y += (vertices[i].y + vertices[i + 1].y) * area;
}
Centroid.X /= 3 * DoubleArea;
Centroid.Y /= 3 * DoubleArea;
centroid.x /= 3 * doubleArea;
centroid.y /= 3 * doubleArea;
return Centroid;
return centroid;
}
} // End of namespace Sword25

View File

@ -42,10 +42,6 @@
namespace Sword25 {
// -----------------------------------------------------------------------------
// Forward Declarations
// -----------------------------------------------------------------------------
class Vertex;
/**
@ -63,12 +59,12 @@ public:
/**
* Copy constructor
*/
Polygon(const Polygon &Other);
Polygon(const Polygon &other);
/**
* Creates a polygon using persisted data
*/
Polygon(InputPersistenceBlock &Reader);
Polygon(InputPersistenceBlock &reader);
/**
* Creaes an object of type #BS_Polygon, and assigns Vertices to it
@ -77,7 +73,7 @@ public:
* @remark The Vertecies that define a polygon must not have any self-intersections.
* If the polygon does have self-intersections, then an empty polygon object is created.
*/
Polygon(int VertexCount, const Vertex *Vertecies);
Polygon(int vertexCount_, const Vertex *vertices_);
/**
* Deletes the BS_Polygon object
@ -95,7 +91,7 @@ public:
* @return Returns false if the Vertecies have self-intersections. In this case,
* the object is not initialised.
*/
bool Init(int VertexCount, const Vertex *Vertecies);
bool init(int vertexCount_, const Vertex *vertices_);
//
// ** Exploratory methods **
@ -107,7 +103,7 @@ public:
* Returns false if the Vertecies of the polygon are arrange counter-clockwise.
* @remark This method only returns a meaningful result if the polygon has at least three Vertecies.
*/
bool IsCW() const;
bool isCW() const;
/**
* Checks whether the Vertices of the polygon are arranged in a counter-clockwise direction.
@ -115,21 +111,21 @@ public:
* Returns false if the Vertecies of the polygon are arranged clockwise or co-planar.
* @remark This method only returns a meaningful result if the polygon has at least three Vertecies.
*/
bool IsCCW() const;
bool isCCW() const;
/**
* Checks whether the polygon is convex.
* @return Returns true if the polygon is convex. Returns false if the polygon is concave.
* @remark This method only returns a meaningful result if the polygon has at least three Vertecies.
*/
bool IsConvex() const;
bool isConvex() const;
/**
* Checks whether the polygon is concave.
* @return Returns true if the polygon is concave. Returns false if the polygon is convex.
* @remark This method only returns a meaningful result if the polygon has at least three Vertecies.
*/
bool IsConcave() const;
bool isConcave() const;
/**
* Checks whether a point is inside the polygon
@ -137,7 +133,7 @@ public:
* @param BorderBelongsToPolygon Specifies whether the edge of the polygon should be considered
* @return Returns true if the point is inside the polygon, false if it is outside.
*/
bool IsPointInPolygon(const Vertex &Vertex, bool BorderBelongsToPolygon = true) const;
bool isPointInPolygon(const Vertex &vertex, bool borderBelongsToPolygon = true) const;
/**
* Checks whether a point is inside the polygon
@ -146,19 +142,19 @@ public:
* @param BorderBelongsToPolygon Specifies whether the edge of the polygon should be considered
* @return Returns true if the point is inside the polygon, false if it is outside.
*/
bool IsPointInPolygon(int X, int Y, bool BorderBelongsToPolygon = true) const;
bool isPointInPolygon(int x, int y, bool borderBelongsToPolygon = true) const;
/**
* Returns the focus/centroid of the polygon
*/
Vertex GetCentroid() const;
Vertex getCentroid() const;
// Edge belongs to the polygon
// Polygon must be CW
bool IsLineInterior(const Vertex &a, const Vertex &b) const;
bool isLineInterior(const Vertex &a, const Vertex &b) const;
// Edge does not belong to the polygon
// Polygon must be CW
bool IsLineExterior(const Vertex &a, const Vertex &b) const;
bool isLineExterior(const Vertex &a, const Vertex &b) const;
//
// Manipulation methods
@ -167,58 +163,58 @@ public:
/**
* Ensures that the Vertecies of the polygon are arranged in a clockwise direction
*/
void EnsureCWOrder();
void ensureCWOrder();
/**
* Ensures that the Vertecies of the polygon are arranged in a counter-clockwise direction
*/
void EnsureCCWOrder();
void ensureCCWOrder();
/**
* Reverses the Vertecies order.
*/
void ReverseVertexOrder();
void reverseVertexOrder();
/**
* Moves the polygon.
* @param Delta The vertex around the polygon to be moved.
*/
void operator+=(const Vertex &Delta);
void operator+=(const Vertex &delta);
//
//------------------
//
/// Specifies the number of Vertecies in the Vertecies array.
int VertexCount;
int vertexCount;
/// COntains the Vertecies of the polygon
Vertex *Vertecies;
Vertex *vertices;
virtual bool persist(OutputPersistenceBlock &writer);
virtual bool unpersist(InputPersistenceBlock &reader);
private:
bool m_IsCW;
bool m_IsConvex;
Vertex m_Centroid;
bool _isCW;
bool _isConvex;
Vertex _centroid;
/**
* Computes the centroid of the polygon.
*/
Vertex ComputeCentroid() const;
Vertex computeCentroid() const;
/**
* Determines how the Vertecies of the polygon are arranged.
* @return Returns true if the Vertecies are arranged in a clockwise
* direction, otherwise false.
*/
bool ComputeIsCW() const;
bool computeIsCW() const;
/**
* Determines whether the polygon is convex or concave.
* @return Returns true if the polygon is convex, otherwise false.
*/
bool ComputeIsConvex() const;
bool computeIsConvex() const;
/**
* Calculates the cross product of three Vertecies
@ -228,7 +224,7 @@ private:
* @return Returns the cross-product of the three vertecies
* @todo This method would be better as a method of the BS_Vertex class
*/
int CrossProduct(const Vertex &V1, const Vertex &V2, const Vertex &V3) const;
int crossProduct(const Vertex &v1, const Vertex &v2, const Vertex &v3) const;
/**
* Computes the scalar product of two vectors spanning three vertecies
@ -241,14 +237,14 @@ private:
* @return Returns the dot product of the three Vertecies.
* @todo This method would be better as a method of the BS_Vertex class
*/
int DotProduct(const Vertex &V1, const Vertex &V2, const Vertex &V3) const;
int dotProduct(const Vertex &v1, const Vertex &v2, const Vertex &v3) const;
/**
* Checks whether the polygon is self-intersecting
* @return Returns true if the polygon is self-intersecting.
* Returns false if the polygon is not self-intersecting.
*/
bool CheckForSelfIntersection() const;
bool checkForSelfIntersection() const;
/**
* Find the vertex of the polygon that is located below the right-most point,
@ -256,9 +252,9 @@ private:
* @return Returns the index of the vertex at the bottom-right of the polygon.
* Returns -1 if the vertex list is empty.
*/
int FindLRVertexIndex() const;
int findLRVertexIndex() const;
bool IsLineInCone(int StartVertexIndex, const Vertex &EndVertex, bool IncludeEdges) const;
bool isLineInCone(int startVertexIndex, const Vertex &endVertex, bool includeEdges) const;
};
} // End of namespace Sword25

View File

@ -43,165 +43,142 @@
namespace Sword25 {
// Constructor / Destructor
// ------------------------
Region::Region() : m_Valid(false), m_Type(RT_REGION) {
RegionRegistry::GetInstance().RegisterObject(this);
Region::Region() : _valid(false), _type(RT_REGION) {
RegionRegistry::getInstance().registerObject(this);
}
// -----------------------------------------------------------------------------
Region::Region(InputPersistenceBlock &Reader, uint Handle) : m_Valid(false), m_Type(RT_REGION) {
RegionRegistry::GetInstance().RegisterObject(this, Handle);
unpersist(Reader);
Region::Region(InputPersistenceBlock &reader, uint handle) : _valid(false), _type(RT_REGION) {
RegionRegistry::getInstance().registerObject(this, handle);
unpersist(reader);
}
// -----------------------------------------------------------------------------
uint Region::Create(REGION_TYPE Type) {
Region *RegionPtr = NULL;
switch (Type) {
uint Region::create(REGION_TYPE type) {
Region *regionPtr = NULL;
switch (type) {
case RT_REGION:
RegionPtr = new Region();
regionPtr = new Region();
break;
case RT_WALKREGION:
RegionPtr = new WalkRegion();
regionPtr = new WalkRegion();
break;
default:
BS_ASSERT(true);
}
return RegionRegistry::GetInstance().ResolvePtr(RegionPtr);
return RegionRegistry::getInstance().resolvePtr(regionPtr);
}
// -----------------------------------------------------------------------------
uint Region::Create(InputPersistenceBlock &reader, uint Handle) {
uint Region::create(InputPersistenceBlock &reader, uint handle) {
// Read type
uint Type;
reader.read(Type);
uint type;
reader.read(type);
// Depending on the type, create a new BS_Region or BS_WalkRegion object
Region *RegionPtr = NULL;
if (Type == RT_REGION) {
RegionPtr = new Region(reader, Handle);
} else if (Type == RT_WALKREGION) {
RegionPtr = new WalkRegion(reader, Handle);
Region *regionPtr = NULL;
if (type == RT_REGION) {
regionPtr = new Region(reader, handle);
} else if (type == RT_WALKREGION) {
regionPtr = new WalkRegion(reader, handle);
} else {
BS_ASSERT(false);
}
return RegionRegistry::GetInstance().ResolvePtr(RegionPtr);
return RegionRegistry::getInstance().resolvePtr(regionPtr);
}
// -----------------------------------------------------------------------------
Region::~Region() {
RegionRegistry::GetInstance().DeregisterObject(this);
RegionRegistry::getInstance().deregisterObject(this);
}
// -----------------------------------------------------------------------------
bool Region::Init(const Polygon &Contour, const Common::Array<Polygon> *pHoles) {
bool Region::init(const Polygon &contour, const Common::Array<Polygon> *pHoles) {
// Reset object state
m_Valid = false;
m_Position = Vertex(0, 0);
m_Polygons.clear();
_valid = false;
_position = Vertex(0, 0);
_polygons.clear();
// Reserve sufficient space for countour and holes in the polygon list
if (pHoles)
m_Polygons.reserve(1 + pHoles->size());
_polygons.reserve(1 + pHoles->size());
else
m_Polygons.reserve(1);
_polygons.reserve(1);
// The first polygon will be the contour
m_Polygons.push_back(Polygon());
m_Polygons[0].Init(Contour.VertexCount, Contour.Vertecies);
_polygons.push_back(Polygon());
_polygons[0].init(contour.vertexCount, contour.vertices);
// Make sure that the Vertecies in the Contour are arranged in a clockwise direction
m_Polygons[0].EnsureCWOrder();
_polygons[0].ensureCWOrder();
// Place the hole polygons in the following positions
if (pHoles) {
for (uint i = 0; i < pHoles->size(); ++i) {
m_Polygons.push_back(Polygon());
m_Polygons[i + 1].Init((*pHoles)[i].VertexCount, (*pHoles)[i].Vertecies);
m_Polygons[i + 1].EnsureCWOrder();
_polygons.push_back(Polygon());
_polygons[i + 1].init((*pHoles)[i].vertexCount, (*pHoles)[i].vertices);
_polygons[i + 1].ensureCWOrder();
}
}
// Initialise bounding box
UpdateBoundingBox();
updateBoundingBox();
m_Valid = true;
_valid = true;
return true;
}
// -----------------------------------------------------------------------------
void Region::updateBoundingBox() {
if (_polygons[0].vertexCount) {
int minX = _polygons[0].vertices[0].x;
int maxX = _polygons[0].vertices[0].x;
int minY = _polygons[0].vertices[0].y;
int maxY = _polygons[0].vertices[0].y;
void Region::UpdateBoundingBox() {
if (m_Polygons[0].VertexCount) {
int MinX = m_Polygons[0].Vertecies[0].X;
int MaxX = m_Polygons[0].Vertecies[0].X;
int MinY = m_Polygons[0].Vertecies[0].Y;
int MaxY = m_Polygons[0].Vertecies[0].Y;
for (int i = 1; i < m_Polygons[0].VertexCount; i++) {
if (m_Polygons[0].Vertecies[i].X < MinX) MinX = m_Polygons[0].Vertecies[i].X;
else if (m_Polygons[0].Vertecies[i].X > MaxX) MaxX = m_Polygons[0].Vertecies[i].X;
if (m_Polygons[0].Vertecies[i].Y < MinY) MinY = m_Polygons[0].Vertecies[i].Y;
else if (m_Polygons[0].Vertecies[i].Y > MaxY) MaxY = m_Polygons[0].Vertecies[i].Y;
for (int i = 1; i < _polygons[0].vertexCount; i++) {
if (_polygons[0].vertices[i].x < minX) minX = _polygons[0].vertices[i].x;
else if (_polygons[0].vertices[i].x > maxX) maxX = _polygons[0].vertices[i].x;
if (_polygons[0].vertices[i].y < minY) minY = _polygons[0].vertices[i].y;
else if (_polygons[0].vertices[i].y > maxY) maxY = _polygons[0].vertices[i].y;
}
m_BoundingBox = Common::Rect(MinX, MinY, MaxX + 1, MaxY + 1);
_boundingBox = Common::Rect(minX, minY, maxX + 1, maxY + 1);
}
}
// Position Changes
// ----------------
void Region::SetPos(int X, int Y) {
void Region::setPos(int x, int y) {
// Calculate the difference between the old and new position
Vertex Delta(X - m_Position.X, Y - m_Position.Y);
Vertex delta(x - _position.x, y - _position.y);
// Save the new position
m_Position = Vertex(X, Y);
_position = Vertex(x, y);
// Move all the vertecies
for (uint i = 0; i < m_Polygons.size(); ++i) {
m_Polygons[i] += Delta;
for (uint i = 0; i < _polygons.size(); ++i) {
_polygons[i] += delta;
}
// Update the bounding box
UpdateBoundingBox();
updateBoundingBox();
}
// -----------------------------------------------------------------------------
void Region::SetPosX(int X) {
SetPos(X, m_Position.Y);
void Region::setPosX(int x) {
setPos(x, _position.y);
}
// -----------------------------------------------------------------------------
void Region::SetPosY(int Y) {
SetPos(m_Position.X, Y);
void Region::setPosY(int y) {
setPos(_position.x, y);
}
// Point-Region Tests
// ------------------
bool Region::IsPointInRegion(int X, int Y) const {
bool Region::isPointInRegion(int x, int y) const {
// Test whether the point is in the bounding box
if (m_BoundingBox.contains(X, Y)) {
if (_boundingBox.contains(x, y)) {
// Test whether the point is in the contour
if (m_Polygons[0].IsPointInPolygon(X, Y, true)) {
if (_polygons[0].isPointInPolygon(x, y, true)) {
// Test whether the point is in a hole
for (uint i = 1; i < m_Polygons.size(); i++) {
if (m_Polygons[i].IsPointInPolygon(X, Y, false))
for (uint i = 1; i < _polygons.size(); i++) {
if (_polygons[i].isPointInPolygon(x, y, false))
return false;
}
@ -212,178 +189,164 @@ bool Region::IsPointInRegion(int X, int Y) const {
return false;
}
// -----------------------------------------------------------------------------
bool Region::IsPointInRegion(const Vertex &Vertex) const {
return IsPointInRegion(Vertex.X, Vertex.Y);
bool Region::isPointInRegion(const Vertex &vertex) const {
return isPointInRegion(vertex.x, vertex.y);
}
// -----------------------------------------------------------------------------
Vertex Region::FindClosestRegionPoint(const Vertex &Point) const {
Vertex Region::findClosestRegionPoint(const Vertex &point) const {
// Determine whether the point is inside a hole. If that is the case, the closest
// point on the edge of the hole is determined
int PolygonIdx = 0;
int polygonIdx = 0;
{
for (uint i = 1; i < m_Polygons.size(); ++i) {
if (m_Polygons[i].IsPointInPolygon(Point)) {
PolygonIdx = i;
for (uint i = 1; i < _polygons.size(); ++i) {
if (_polygons[i].isPointInPolygon(point)) {
polygonIdx = i;
break;
}
}
}
const Polygon &Polygon = m_Polygons[PolygonIdx];
const Polygon &polygon = _polygons[polygonIdx];
BS_ASSERT(Polygon.VertexCount > 1);
BS_ASSERT(polygon.vertexCount > 1);
// For each line of the polygon, calculate the point that is cloest to the given point
// The point of this set with the smallest distance to the given point is the result.
Vertex ClosestVertex = FindClosestPointOnLine(Polygon.Vertecies[0], Polygon.Vertecies[1], Point);
int ClosestVertexDistance2 = ClosestVertex.Distance(Point);
for (int i = 1; i < Polygon.VertexCount; ++i) {
int j = (i + 1) % Polygon.VertexCount;
Vertex closestVertex = findClosestPointOnLine(polygon.vertices[0], polygon.vertices[1], point);
int closestVertexDistance2 = closestVertex.distance(point);
for (int i = 1; i < polygon.vertexCount; ++i) {
int j = (i + 1) % polygon.vertexCount;
Vertex CurVertex = FindClosestPointOnLine(Polygon.Vertecies[i], Polygon.Vertecies[j], Point);
if (CurVertex.Distance(Point) < ClosestVertexDistance2) {
ClosestVertex = CurVertex;
ClosestVertexDistance2 = CurVertex.Distance(Point);
Vertex curVertex = findClosestPointOnLine(polygon.vertices[i], polygon.vertices[j], point);
if (curVertex.distance(point) < closestVertexDistance2) {
closestVertex = curVertex;
closestVertexDistance2 = curVertex.distance(point);
}
}
// Determine whether the point is really within the region. This must not be so, as a result of rounding
// errors can occur at the edge of polygons
if (IsPointInRegion(ClosestVertex))
return ClosestVertex;
if (isPointInRegion(closestVertex))
return closestVertex;
else {
// Try to construct a point within the region - 8 points are tested in the immediate vacinity
// of the point
if (IsPointInRegion(ClosestVertex + Vertex(-2, -2)))
return ClosestVertex + Vertex(-2, -2);
else if (IsPointInRegion(ClosestVertex + Vertex(0, -2)))
return ClosestVertex + Vertex(0, -2);
else if (IsPointInRegion(ClosestVertex + Vertex(2, -2)))
return ClosestVertex + Vertex(2, -2);
else if (IsPointInRegion(ClosestVertex + Vertex(-2, 0)))
return ClosestVertex + Vertex(-2, 0);
else if (IsPointInRegion(ClosestVertex + Vertex(0, 2)))
return ClosestVertex + Vertex(0, 2);
else if (IsPointInRegion(ClosestVertex + Vertex(-2, 2)))
return ClosestVertex + Vertex(-2, 2);
else if (IsPointInRegion(ClosestVertex + Vertex(-2, 0)))
return ClosestVertex + Vertex(2, 2);
else if (IsPointInRegion(ClosestVertex + Vertex(2, 2)))
return ClosestVertex + Vertex(2, 2);
if (isPointInRegion(closestVertex + Vertex(-2, -2)))
return closestVertex + Vertex(-2, -2);
else if (isPointInRegion(closestVertex + Vertex(0, -2)))
return closestVertex + Vertex(0, -2);
else if (isPointInRegion(closestVertex + Vertex(2, -2)))
return closestVertex + Vertex(2, -2);
else if (isPointInRegion(closestVertex + Vertex(-2, 0)))
return closestVertex + Vertex(-2, 0);
else if (isPointInRegion(closestVertex + Vertex(0, 2)))
return closestVertex + Vertex(0, 2);
else if (isPointInRegion(closestVertex + Vertex(-2, 2)))
return closestVertex + Vertex(-2, 2);
else if (isPointInRegion(closestVertex + Vertex(-2, 0)))
return closestVertex + Vertex(2, 2);
else if (isPointInRegion(closestVertex + Vertex(2, 2)))
return closestVertex + Vertex(2, 2);
// If no point could be found that way that lies within the region, find the next point
ClosestVertex = Polygon.Vertecies[0];
int ShortestVertexDistance2 = Polygon.Vertecies[0].Distance2(Point);
closestVertex = polygon.vertices[0];
int shortestVertexDistance2 = polygon.vertices[0].distance2(point);
{
for (int i = 1; i < Polygon.VertexCount; i++) {
int CurDistance2 = Polygon.Vertecies[i].Distance2(Point);
if (CurDistance2 < ShortestVertexDistance2) {
ClosestVertex = Polygon.Vertecies[i];
ShortestVertexDistance2 = CurDistance2;
for (int i = 1; i < polygon.vertexCount; i++) {
int curDistance2 = polygon.vertices[i].distance2(point);
if (curDistance2 < shortestVertexDistance2) {
closestVertex = polygon.vertices[i];
shortestVertexDistance2 = curDistance2;
}
}
}
BS_LOG_WARNINGLN("Clostest vertex forced because edgepoint was outside region.");
return ClosestVertex;
return closestVertex;
}
}
// -----------------------------------------------------------------------------
Vertex Region::findClosestPointOnLine(const Vertex &lineStart, const Vertex &lineEnd, const Vertex point) const {
float vector1X = static_cast<float>(point.x - lineStart.x);
float vector1Y = static_cast<float>(point.y - lineStart.y);
float vector2X = static_cast<float>(lineEnd.x - lineStart.x);
float vector2Y = static_cast<float>(lineEnd.y - lineStart.y);
float vector2Length = sqrtf(vector2X * vector2X + vector2Y * vector2Y);
vector2X /= vector2Length;
vector2Y /= vector2Length;
float distance = sqrtf(static_cast<float>((lineStart.x - lineEnd.x) * (lineStart.x - lineEnd.x) +
(lineStart.y - lineEnd.y) * (lineStart.y - lineEnd.y)));
float dot = vector1X * vector2X + vector1Y * vector2Y;
Vertex Region::FindClosestPointOnLine(const Vertex &LineStart, const Vertex &LineEnd, const Vertex Point) const {
float Vector1X = static_cast<float>(Point.X - LineStart.X);
float Vector1Y = static_cast<float>(Point.Y - LineStart.Y);
float Vector2X = static_cast<float>(LineEnd.X - LineStart.X);
float Vector2Y = static_cast<float>(LineEnd.Y - LineStart.Y);
float Vector2Length = sqrtf(Vector2X * Vector2X + Vector2Y * Vector2Y);
Vector2X /= Vector2Length;
Vector2Y /= Vector2Length;
float Distance = sqrtf(static_cast<float>((LineStart.X - LineEnd.X) * (LineStart.X - LineEnd.X) +
(LineStart.Y - LineEnd.Y) * (LineStart.Y - LineEnd.Y)));
float Dot = Vector1X * Vector2X + Vector1Y * Vector2Y;
if (dot <= 0)
return lineStart;
if (dot >= distance)
return lineEnd;
if (Dot <= 0) return LineStart;
if (Dot >= Distance) return LineEnd;
Vertex Vector3(static_cast<int>(Vector2X * Dot + 0.5f), static_cast<int>(Vector2Y * Dot + 0.5f));
return LineStart + Vector3;
Vertex vector3(static_cast<int>(vector2X * dot + 0.5f), static_cast<int>(vector2Y * dot + 0.5f));
return lineStart + vector3;
}
// -----------------------------------------------------------------------------
// Line of Sight
// -----------------------------------------------------------------------------
bool Region::IsLineOfSight(const Vertex &a, const Vertex &b) const {
BS_ASSERT(m_Polygons.size());
bool Region::isLineOfSight(const Vertex &a, const Vertex &b) const {
BS_ASSERT(_polygons.size());
// The line must be within the contour polygon, and outside of any hole polygons
Common::Array<Polygon>::const_iterator iter = m_Polygons.begin();
if (!(*iter).IsLineInterior(a, b)) return false;
for (iter++; iter != m_Polygons.end(); iter++)
if (!(*iter).IsLineExterior(a, b)) return false;
Common::Array<Polygon>::const_iterator iter = _polygons.begin();
if (!(*iter).isLineInterior(a, b)) return false;
for (iter++; iter != _polygons.end(); iter++)
if (!(*iter).isLineExterior(a, b)) return false;
return true;
}
// -----------------------------------------------------------------------------
// Persistence
// -----------------------------------------------------------------------------
bool Region::persist(OutputPersistenceBlock &writer) {
bool Result = true;
writer.write(static_cast<uint>(m_Type));
writer.write(m_Valid);
writer.write(m_Position.X);
writer.write(m_Position.Y);
writer.write(static_cast<uint>(_type));
writer.write(_valid);
writer.write(_position.x);
writer.write(_position.y);
writer.write(m_Polygons.size());
Common::Array<Polygon>::iterator It = m_Polygons.begin();
while (It != m_Polygons.end()) {
writer.write(_polygons.size());
Common::Array<Polygon>::iterator It = _polygons.begin();
while (It != _polygons.end()) {
Result &= It->persist(writer);
++It;
}
writer.write(m_BoundingBox.left);
writer.write(m_BoundingBox.top);
writer.write(m_BoundingBox.right);
writer.write(m_BoundingBox.bottom);
writer.write(_boundingBox.left);
writer.write(_boundingBox.top);
writer.write(_boundingBox.right);
writer.write(_boundingBox.bottom);
return Result;
}
// -----------------------------------------------------------------------------
bool Region::unpersist(InputPersistenceBlock &reader) {
reader.read(m_Valid);
reader.read(m_Position.X);
reader.read(m_Position.Y);
reader.read(_valid);
reader.read(_position.x);
reader.read(_position.y);
m_Polygons.clear();
_polygons.clear();
uint PolygonCount;
reader.read(PolygonCount);
for (uint i = 0; i < PolygonCount; ++i) {
m_Polygons.push_back(Polygon(reader));
_polygons.push_back(Polygon(reader));
}
reader.read(m_BoundingBox.left);
reader.read(m_BoundingBox.top);
reader.read(m_BoundingBox.right);
reader.read(m_BoundingBox.bottom);
reader.read(_boundingBox.left);
reader.read(_boundingBox.top);
reader.read(_boundingBox.right);
reader.read(_boundingBox.bottom);
return reader.isGood();
}
// -----------------------------------------------------------------------------
Vertex Region::GetCentroid() const {
if (m_Polygons.size() > 0)
return m_Polygons[0].GetCentroid();
Vertex Region::getCentroid() const {
if (_polygons.size() > 0)
return _polygons[0].getCentroid();
return
Vertex();
}

View File

@ -62,7 +62,7 @@ protected:
*/
Region();
Region(InputPersistenceBlock &Reader, uint Handle);
Region(InputPersistenceBlock &reader, uint handle);
public:
enum REGION_TYPE {
@ -70,8 +70,8 @@ public:
RT_WALKREGION
};
static uint Create(REGION_TYPE Type);
static uint Create(InputPersistenceBlock &Reader, uint Handle = 0);
static uint create(REGION_TYPE type);
static uint create(InputPersistenceBlock &reader, uint handle = 0);
virtual ~Region();
@ -83,7 +83,7 @@ public:
* @return Returns true if the initialisation was successful, otherwise false.
* @remark If the region was already initialised, the old state will be deleted.
*/
virtual bool Init(const Polygon &Contour, const Common::Array<Polygon> *pHoles = NULL);
virtual bool init(const Polygon &contour, const Common::Array<Polygon> *pHoles = NULL);
//
// Exploratory Methods
@ -94,29 +94,29 @@ public:
* @return Returns true if the object is in a valid state, otherwise false.
* @remark Invalid objects can be made valid by calling Init with a valid state.
*/
bool IsValid() const {
return m_Valid;
bool isValid() const {
return _valid;
}
/**
* Returns the position of the region
*/
const Vertex &GetPosition() const {
return m_Position;
const Vertex &getPosition() const {
return _position;
}
/**
* Returns the X position of the region
*/
int GetPosX() const {
return m_Position.X;
int getPosX() const {
return _position.x;
}
/**
* Returns the Y position of the region
*/
int GetPosY() const {
return m_Position.Y;
int getPosY() const {
return _position.y;
}
/**
@ -124,7 +124,7 @@ public:
* @param Vertex A verex with the co-ordinates of the test point
* @return Returns true if the point is within the region, otherwise false.
*/
bool IsPointInRegion(const Vertex &Vertex) const;
bool isPointInRegion(const Vertex &vertex) const;
/**
* Indicates whether a point is inside the region
@ -132,20 +132,20 @@ public:
* @param Y The Y position
* @return Returns true if the point is within the region, otherwise false.
*/
bool IsPointInRegion(int X, int Y) const;
bool isPointInRegion(int x, int y) const;
/**
* Returns the countour of the region
*/
const Polygon &GetContour() const {
return m_Polygons[0];
const Polygon &getContour() const {
return _polygons[0];
}
/**
* Returns the number of polygons in the hole region
*/
int GetHoleCount() const {
return static_cast<int>(m_Polygons.size() - 1);
int getHoleCount() const {
return static_cast<int>(_polygons.size() - 1);
}
/**
@ -154,7 +154,7 @@ public:
* The index must be between 0 and GetHoleCount() - 1.
* @return Returns the desired hole polygon
*/
inline const Polygon &GetHole(uint i) const;
inline const Polygon &getHole(uint i) const;
/**
* For a point outside the region, finds the closest point inside the region
@ -164,14 +164,14 @@ public:
* One should not therefore rely on the fact that there is really no point in
* the region which is closer to the given point.
*/
Vertex FindClosestRegionPoint(const Vertex &Point) const;
Vertex findClosestRegionPoint(const Vertex &point) const;
/**
* Returns the centroid for the region
*/
Vertex GetCentroid() const;
Vertex getCentroid() const;
bool IsLineOfSight(const Vertex &a, const Vertex &b) const;
bool isLineOfSight(const Vertex &a, const Vertex &b) const;
//
// Manipulation Methods
@ -182,19 +182,19 @@ public:
* @param X The new X psoition of the region
* @param Y The new Y psoition of the region
*/
virtual void SetPos(int X, int Y);
virtual void setPos(int x, int y);
/**
* Sets the X position of the region
* @param X The new X position of the region
*/
void SetPosX(int X);
void setPosX(int x);
/**
* Sets the Y position of the region
* @param Y The new Y position of the region
*/
void SetPosY(int Y);
void setPosY(int y);
//
// Manipulation Methods
@ -205,21 +205,21 @@ public:
protected:
/// This specifies the type of object
REGION_TYPE m_Type;
REGION_TYPE _type;
/// This variable indicates whether the current object state is valid
bool m_Valid;
bool _valid;
/// This vertex is the position of the region
Vertex m_Position;
Vertex _position;
/// This array contains all the polygons that define the region. The first element of
// the array is the contour, all others are the holes
Common::Array<Polygon> m_Polygons;
Common::Array<Polygon> _polygons;
/// The bounding box for the region
Common::Rect m_BoundingBox;
Common::Rect _boundingBox;
/**
* Updates the bounding box of the region.
*/
void UpdateBoundingBox();
void updateBoundingBox();
/**
* Find the point on a line which is closest to another point
@ -228,17 +228,12 @@ protected:
* @param Point The point to be compared against
* @return Returns the point on the line which is cloest to the passed point.
*/
Vertex FindClosestPointOnLine(const Vertex &LineStart, const Vertex &LineEnd, const Vertex Point) const;
Vertex findClosestPointOnLine(const Vertex &lineStart, const Vertex &lineEnd, const Vertex point) const;
};
// -----------------------------------------------------------------------------
// Inlines
// -----------------------------------------------------------------------------
inline const Polygon &Region::GetHole(uint i) const {
BS_ASSERT(i < m_Polygons.size() - 1);
return m_Polygons[i + 1];
inline const Polygon &Region::getHole(uint i) const {
BS_ASSERT(i < _polygons.size() - 1);
return _polygons[i + 1];
}
} // End of namespace Sword25

View File

@ -32,16 +32,8 @@
*
*/
// -----------------------------------------------------------------------------
// Logging
// -----------------------------------------------------------------------------
#define BS_LOG_PREFIX "REGIONREGISTRY"
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include "sword25/kernel/outputpersistenceblock.h"
#include "sword25/kernel/inputpersistenceblock.h"
#include "sword25/math/regionregistry.h"
@ -49,77 +41,66 @@
namespace Sword25 {
// -----------------------------------------------------------------------------
// Implementation
// -----------------------------------------------------------------------------
Common::SharedPtr<RegionRegistry> RegionRegistry::_instancePtr;
Common::SharedPtr<RegionRegistry> RegionRegistry::m_InstancePtr;
// -----------------------------------------------------------------------------
void RegionRegistry::LogErrorLn(const char *Message) const {
BS_LOG_ERRORLN(Message);
void RegionRegistry::logErrorLn(const char *message) const {
BS_LOG_ERRORLN(message);
}
// -----------------------------------------------------------------------------
void RegionRegistry::LogWarningLn(const char *Message) const {
BS_LOG_WARNINGLN(Message);
void RegionRegistry::logWarningLn(const char *message) const {
BS_LOG_WARNINGLN(message);
}
// -----------------------------------------------------------------------------
bool RegionRegistry::persist(OutputPersistenceBlock &writer) {
bool Result = true;
bool result = true;
// write out the next handle
writer.write(m_NextHandle);
writer.write(_nextHandle);
// Number of regions to write
writer.write(m_Handle2PtrMap.size());
writer.write(_handle2PtrMap.size());
// Persist all the BS_Regions
HANDLE2PTR_MAP::const_iterator Iter = m_Handle2PtrMap.begin();
while (Iter != m_Handle2PtrMap.end()) {
HANDLE2PTR_MAP::const_iterator iter = _handle2PtrMap.begin();
while (iter != _handle2PtrMap.end()) {
// Handle persistence
writer.write(Iter->_key);
writer.write(iter->_key);
// Persist object
Result &= Iter->_value->persist(writer);
result &= iter->_value->persist(writer);
++Iter;
++iter;
}
return Result;
return result;
}
// -----------------------------------------------------------------------------
bool RegionRegistry::unpersist(InputPersistenceBlock &reader) {
bool Result = true;
bool result = true;
// read in the next handle
reader.read(m_NextHandle);
reader.read(_nextHandle);
// Destroy all existing BS_Regions
//FIXME: This doesn't seem right - the value is being deleted but not the actual hash node itself?
while (!m_Handle2PtrMap.empty()) delete m_Handle2PtrMap.begin()->_value;
while (!_handle2PtrMap.empty())
delete _handle2PtrMap.begin()->_value;
// read in the number of BS_Regions
uint RegionCount;
reader.read(RegionCount);
uint regionCount;
reader.read(regionCount);
// Restore all the BS_Regions objects
for (uint i = 0; i < RegionCount; ++i) {
for (uint i = 0; i < regionCount; ++i) {
// Handle read
uint Handle;
reader.read(Handle);
uint handle;
reader.read(handle);
// BS_Region restore
Result &= Region::Create(reader, Handle) != 0;
result &= Region::create(reader, handle) != 0;
}
return reader.isGood() && Result;
return reader.isGood() && result;
}
} // End of namespace Sword25

View File

@ -35,10 +35,6 @@
#ifndef SWORD25_REGIONREGISTRY_H
#define SWORD25_REGIONREGISTRY_H
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include "common/ptr.h"
#include "sword25/kernel/common.h"
#include "sword25/kernel/persistable.h"
@ -46,31 +42,23 @@
namespace Sword25 {
// -----------------------------------------------------------------------------
// Forward Declarations
// -----------------------------------------------------------------------------
class Region;
// -----------------------------------------------------------------------------
// Class definitions
// -----------------------------------------------------------------------------
class RegionRegistry : public ObjectRegistry<Region>, public Persistable {
public:
static RegionRegistry &GetInstance() {
if (!m_InstancePtr.get()) m_InstancePtr = Common::SharedPtr<RegionRegistry>(new RegionRegistry());
return *m_InstancePtr.get();
static RegionRegistry &getInstance() {
if (!_instancePtr.get()) _instancePtr = Common::SharedPtr<RegionRegistry>(new RegionRegistry());
return *_instancePtr.get();
}
virtual bool persist(OutputPersistenceBlock &writer);
virtual bool unpersist(InputPersistenceBlock &reader);
private:
virtual void LogErrorLn(const char *Message) const;
virtual void LogWarningLn(const char *Message) const;
virtual void logErrorLn(const char *message) const;
virtual void logWarningLn(const char *message) const;
static Common::SharedPtr<RegionRegistry> m_InstancePtr;
static Common::SharedPtr<RegionRegistry> _instancePtr;
};
} // End of namespace Sword25

View File

@ -44,30 +44,28 @@ extern "C"
}
// -----------------------------------------------------------------------------
namespace Sword25 {
Vertex &Vertex::LuaVertexToVertex(lua_State *L, int StackIndex, Vertex &vertex) {
Vertex &Vertex::luaVertexToVertex(lua_State *L, int stackIndex, Vertex &vertex) {
#ifdef DEBUG
int __startStackDepth = lua_gettop(L);
#endif
// Ensure that we actually consider a table
luaL_checktype(L, StackIndex, LUA_TTABLE);
luaL_checktype(L, stackIndex, LUA_TTABLE);
// Read X Component
lua_pushstring(L, "X");
lua_gettable(L, StackIndex);
if (!lua_isnumber(L, -1)) luaL_argcheck(L, 0, StackIndex, "the X component has to be a number");
vertex.X = static_cast<int>(lua_tonumber(L, -1));
lua_gettable(L, stackIndex);
if (!lua_isnumber(L, -1)) luaL_argcheck(L, 0, stackIndex, "the X component has to be a number");
vertex.x = static_cast<int>(lua_tonumber(L, -1));
lua_pop(L, 1);
// Read Y Component
lua_pushstring(L, "Y");
lua_gettable(L, StackIndex);
if (!lua_isnumber(L, -1)) luaL_argcheck(L, 0, StackIndex, "the Y component has to be a number");
vertex.Y = static_cast<int>(lua_tonumber(L, -1));
lua_gettable(L, stackIndex);
if (!lua_isnumber(L, -1)) luaL_argcheck(L, 0, stackIndex, "the Y component has to be a number");
vertex.y = static_cast<int>(lua_tonumber(L, -1));
lua_pop(L, 1);
#ifdef DEBUG
@ -77,20 +75,18 @@ Vertex &Vertex::LuaVertexToVertex(lua_State *L, int StackIndex, Vertex &vertex)
return vertex;
}
// -----------------------------------------------------------------------------
void Vertex::VertexToLuaVertex(lua_State *L, const Vertex &vertex) {
void Vertex::vertexToLuaVertex(lua_State *L, const Vertex &vertex) {
// Create New Table
lua_newtable(L);
// X value is written to table
lua_pushstring(L, "X");
lua_pushnumber(L, vertex.X);
lua_pushnumber(L, vertex.x);
lua_settable(L, -3);
// Y value is written to table
lua_pushstring(L, "Y");
lua_pushnumber(L, vertex.Y);
lua_pushnumber(L, vertex.y);
lua_settable(L, -3);
}

View File

@ -62,57 +62,57 @@ namespace Sword25 {
*/
class Vertex {
public:
Vertex() : X(0), Y(0) {};
Vertex(int X_, int Y_) {
this->X = X_;
this->Y = Y_;
Vertex() : x(0), y(0) {};
Vertex(int x_, int y_) {
this->x = x_;
this->y = y_;
}
int X;
int Y;
int x;
int y;
/**
* Compares two Vertecies.
*/
inline bool operator==(const Vertex &rhs) const {
if (X == rhs.X && Y == rhs.Y) return true;
if (x == rhs.x && y == rhs.y) return true;
return false;
}
/**
* Compares two Vertecies.
*/
inline bool operator!=(const Vertex &rhs) const {
if (X != rhs.X || Y != rhs.Y) return true;
if (x != rhs.x || y != rhs.y) return true;
return false;
}
/**
* Adds a vertex to vertex
*/
inline void operator+=(const Vertex &Delta) {
X += Delta.X;
Y += Delta.Y;
inline void operator+=(const Vertex &delta) {
x += delta.x;
y += delta.y;
}
/**
* Subtracts a vertex from a vertex
*/
inline void operator-=(const Vertex &Delta) {
X -= Delta.X;
Y -= Delta.Y;
inline void operator-=(const Vertex &delta) {
x -= delta.x;
y -= delta.y;
}
/**
* Adds two vertecies
*/
inline Vertex operator+(const Vertex &Delta) const {
return Vertex(X + Delta.X, Y + Delta.Y);
inline Vertex operator+(const Vertex &delta) const {
return Vertex(x + delta.x, y + delta.y);
}
/**
* Subtracts two vertecies
*/
inline Vertex operator-(const Vertex &Delta) const {
return Vertex(X - Delta.X, Y - Delta.Y);
inline Vertex operator-(const Vertex &delta) const {
return Vertex(x - delta.x, y - delta.y);
}
/**
@ -122,8 +122,8 @@ public:
* @remark If only distances should be compared, this method should be used because
* it is faster than Distance()
*/
inline int Distance2(const Vertex &vertex) const {
return (X - vertex.X) * (X - vertex.X) + (Y - vertex.Y) * (Y - vertex.Y);
inline int distance2(const Vertex &vertex) const {
return (x - vertex.x) * (x - vertex.x) + (y - vertex.y) * (y - vertex.y);
}
/**
@ -132,8 +132,8 @@ public:
* @return Returns the square of the distance between itself and the passed vertex
* @remark If only distances should be compared, Distance2() should be used, since it is faster.
*/
inline int Distance(const Vertex &vertex) const {
return (int)(sqrtf(static_cast<float>(Distance2(vertex))) + 0.5);
inline int distance(const Vertex &vertex) const {
return (int)(sqrtf(static_cast<float>(distance2(vertex))) + 0.5);
}
/**
@ -142,8 +142,8 @@ public:
* @param Vertex The second vertex
* @return Returns the cross product of this vertex and the passed vertex.
*/
inline int ComputeCrossProduct(const Vertex &vertex) const {
return X * vertex.Y - vertex.X * Y;
inline int computeCrossProduct(const Vertex &vertex) const {
return x * vertex.y - vertex.x * y;
}
/**
@ -151,8 +151,8 @@ public:
* @param Vertex The second vertex
* @return Returns the dot product of this vertex and the passed vertex.
*/
inline int ComputeDotProduct(const Vertex &vertex) const {
return X * vertex.X + Y * vertex.Y;
inline int computeDotProduct(const Vertex &vertex) const {
return x * vertex.x + y * vertex.y;
}
/**
@ -160,19 +160,19 @@ public:
* @param Vertex The second vertex
* @return Returns the angle between this vertex and the passed vertex in radians.
*/
inline float ComputeAngle(const Vertex &vertex) const {
return atan2f(static_cast<float>(ComputeCrossProduct(vertex)), static_cast<float>(ComputeDotProduct(vertex)));
inline float computeAngle(const Vertex &vertex) const {
return atan2f(static_cast<float>(computeCrossProduct(vertex)), static_cast<float>(computeDotProduct(vertex)));
}
/**
* Calculates the length of the vector
*/
inline float ComputeLength() const {
return sqrtf(static_cast<float>(X * X + Y * Y));
inline float computeLength() const {
return sqrtf(static_cast<float>(x * x + y * y));
}
static Vertex &LuaVertexToVertex(lua_State *L, int StackIndex, Vertex &vertex);
static void VertexToLuaVertex(lua_State *L, const Vertex &vertex);
static Vertex &luaVertexToVertex(lua_State *L, int StackIndex, Vertex &vertex);
static void vertexToLuaVertex(lua_State *L, const Vertex &vertex);
};
} // End of namespace Sword25

View File

@ -42,193 +42,177 @@
namespace Sword25 {
// -----------------------------------------------------------------------------
// Constants
// -----------------------------------------------------------------------------
static const int infinity = 0x7fffffff;
// -----------------------------------------------------------------------------
// Constructor / Destructor
// -----------------------------------------------------------------------------
static const int Infinity = 0x7fffffff;
WalkRegion::WalkRegion() {
m_Type = RT_WALKREGION;
_type = RT_WALKREGION;
}
// -----------------------------------------------------------------------------
WalkRegion::WalkRegion(InputPersistenceBlock &Reader, uint Handle) :
Region(Reader, Handle) {
m_Type = RT_WALKREGION;
unpersist(Reader);
WalkRegion::WalkRegion(InputPersistenceBlock &reader, uint handle) :
Region(reader, handle) {
_type = RT_WALKREGION;
unpersist(reader);
}
// -----------------------------------------------------------------------------
WalkRegion::~WalkRegion() {
}
// -----------------------------------------------------------------------------
bool WalkRegion::Init(const Polygon &Contour, const Common::Array<Polygon> *pHoles) {
bool WalkRegion::init(const Polygon &contour, const Common::Array<Polygon> *pHoles) {
// Default initialisation of the region
if (!Region::Init(Contour, pHoles)) return false;
if (!Region::init(contour, pHoles)) return false;
// Prepare structures for pathfinding
InitNodeVector();
ComputeVisibilityMatrix();
initNodeVector();
computeVisibilityMatrix();
// Signal success
return true;
}
// -----------------------------------------------------------------------------
bool WalkRegion::QueryPath(Vertex StartPoint, Vertex EndPoint, BS_Path &Path) {
BS_ASSERT(Path.empty());
bool WalkRegion::queryPath(Vertex startPoint, Vertex endPoint, BS_Path &path) {
BS_ASSERT(path.empty());
// If the start and finish are identical, no path can be found trivially
if (StartPoint == EndPoint) return true;
if (startPoint == endPoint)
return true;
// Ensure that the start and finish are valid and find new start points if either
// are outside the polygon
if (!CheckAndPrepareStartAndEnd(StartPoint, EndPoint)) return false;
if (!checkAndPrepareStartAndEnd(startPoint, endPoint)) return false;
// If between the start and point a line of sight exists, then it can be returned.
if (IsLineOfSight(StartPoint, EndPoint)) {
Path.push_back(StartPoint);
Path.push_back(EndPoint);
if (isLineOfSight(startPoint, endPoint)) {
path.push_back(startPoint);
path.push_back(endPoint);
return true;
}
return FindPath(StartPoint, EndPoint, Path);
return findPath(startPoint, endPoint, path);
}
// -----------------------------------------------------------------------------
struct DijkstraNode {
typedef Common::Array<DijkstraNode> Container;
typedef Container::iterator Iter;
typedef Container::const_iterator ConstIter;
DijkstraNode() : Cost(infinity), Chosen(false) {};
ConstIter ParentIter;
int Cost;
bool Chosen;
DijkstraNode() : cost(Infinity), chosen(false) {};
ConstIter parentIter;
int cost;
bool chosen;
};
static void InitDijkstraNodes(DijkstraNode::Container &DijkstraNodes, const Region &Region,
const Vertex &Start, const Common::Array<Vertex> &Nodes) {
static void initDijkstraNodes(DijkstraNode::Container &dijkstraNodes, const Region &region,
const Vertex &start, const Common::Array<Vertex> &nodes) {
// Allocate sufficient space in the array
DijkstraNodes.resize(Nodes.size());
dijkstraNodes.resize(nodes.size());
// Initialise all the nodes which are visible from the starting node
DijkstraNode::Iter DijkstraIter = DijkstraNodes.begin();
for (Common::Array<Vertex>::const_iterator NodesIter = Nodes.begin();
NodesIter != Nodes.end(); NodesIter++, DijkstraIter++) {
(*DijkstraIter).ParentIter = DijkstraNodes.end();
if (Region.IsLineOfSight(*NodesIter, Start))(*DijkstraIter).Cost = (*NodesIter).Distance(Start);
DijkstraNode::Iter dijkstraIter = dijkstraNodes.begin();
for (Common::Array<Vertex>::const_iterator nodesIter = nodes.begin();
nodesIter != nodes.end(); nodesIter++, dijkstraIter++) {
(*dijkstraIter).parentIter = dijkstraNodes.end();
if (region.isLineOfSight(*nodesIter, start))(*dijkstraIter).cost = (*nodesIter).distance(start);
}
BS_ASSERT(DijkstraIter == DijkstraNodes.end());
BS_ASSERT(dijkstraIter == dijkstraNodes.end());
}
static DijkstraNode::Iter ChooseClosestNode(DijkstraNode::Container &Nodes) {
DijkstraNode::Iter ClosestNodeInter = Nodes.end();
int MinCost = infinity;
static DijkstraNode::Iter chooseClosestNode(DijkstraNode::Container &nodes) {
DijkstraNode::Iter closestNodeInter = nodes.end();
int minCost = Infinity;
for (DijkstraNode::Iter iter = Nodes.begin(); iter != Nodes.end(); iter++) {
if (!(*iter).Chosen && (*iter).Cost < MinCost) {
MinCost = (*iter).Cost;
ClosestNodeInter = iter;
for (DijkstraNode::Iter iter = nodes.begin(); iter != nodes.end(); iter++) {
if (!(*iter).chosen && (*iter).cost < minCost) {
minCost = (*iter).cost;
closestNodeInter = iter;
}
}
return ClosestNodeInter;
return closestNodeInter;
}
static void RelaxNodes(DijkstraNode::Container &Nodes,
const Common::Array< Common::Array<int> > &VisibilityMatrix,
const DijkstraNode::ConstIter &CurNodeIter) {
static void relaxNodes(DijkstraNode::Container &nodes,
const Common::Array< Common::Array<int> > &visibilityMatrix,
const DijkstraNode::ConstIter &curNodeIter) {
// All the successors of the current node that have not been chosen will be
// inserted into the boundary node list, and the cost will be updated if
// a shorter path has been found to them.
int CurNodeIndex = CurNodeIter - Nodes.begin();
for (uint i = 0; i < Nodes.size(); i++) {
int Cost = VisibilityMatrix[CurNodeIndex][i];
if (!Nodes[i].Chosen && Cost != infinity) {
int TotalCost = (*CurNodeIter).Cost + Cost;
if (TotalCost < Nodes[i].Cost) {
Nodes[i].ParentIter = CurNodeIter;
Nodes[i].Cost = TotalCost;
int curNodeIndex = curNodeIter - nodes.begin();
for (uint i = 0; i < nodes.size(); i++) {
int cost = visibilityMatrix[curNodeIndex][i];
if (!nodes[i].chosen && cost != Infinity) {
int totalCost = (*curNodeIter).cost + cost;
if (totalCost < nodes[i].cost) {
nodes[i].parentIter = curNodeIter;
nodes[i].cost = totalCost;
}
}
}
}
static void RelaxEndPoint(const Vertex &CurNodePos,
const DijkstraNode::ConstIter &CurNodeIter,
const Vertex &EndPointPos,
DijkstraNode &EndPoint,
const Region &Region) {
if (Region.IsLineOfSight(CurNodePos, EndPointPos)) {
int TotalCost = (*CurNodeIter).Cost + CurNodePos.Distance(EndPointPos);
if (TotalCost < EndPoint.Cost) {
EndPoint.ParentIter = CurNodeIter;
EndPoint.Cost = TotalCost;
static void relaxEndPoint(const Vertex &curNodePos,
const DijkstraNode::ConstIter &curNodeIter,
const Vertex &endPointPos,
DijkstraNode &endPoint,
const Region &region) {
if (region.isLineOfSight(curNodePos, endPointPos)) {
int totalCost = (*curNodeIter).cost + curNodePos.distance(endPointPos);
if (totalCost < endPoint.cost) {
endPoint.parentIter = curNodeIter;
endPoint.cost = totalCost;
}
}
}
bool WalkRegion::FindPath(const Vertex &Start, const Vertex &End, BS_Path &Path) const {
bool WalkRegion::findPath(const Vertex &start, const Vertex &end, BS_Path &path) const {
// This is an implementation of Dijkstra's algorithm
// Initialise edge node list
DijkstraNode::Container DijkstraNodes;
InitDijkstraNodes(DijkstraNodes, *this, Start, m_Nodes);
DijkstraNode::Container dijkstraNodes;
initDijkstraNodes(dijkstraNodes, *this, start, _nodes);
// The end point is treated separately, since it does not exist in the visibility graph
DijkstraNode EndPoint;
DijkstraNode endPoint;
// Since a node is selected each round from the node list, and can never be selected again
// after that, the maximum number of loop iterations is limited by the number of nodes
for (uint i = 0; i < m_Nodes.size(); i++) {
for (uint i = 0; i < _nodes.size(); i++) {
// Determine the nearest edge node in the node list
DijkstraNode::Iter NodeInter = ChooseClosestNode(DijkstraNodes);
DijkstraNode::Iter nodeInter = chooseClosestNode(dijkstraNodes);
// If no free nodes are absent from the edge node list, there is no path from start
// to end node. This case should never occur, since the number of loop passes is
// limited, but etter safe than sorry
if (NodeInter == DijkstraNodes.end()) return false;
if (nodeInter == dijkstraNodes.end())
return false;
// If the destination point is closer than the point cost, scan can stop
(*NodeInter).Chosen = true;
if (EndPoint.Cost <= (*NodeInter).Cost) {
(*nodeInter).chosen = true;
if (endPoint.cost <= (*nodeInter).cost) {
// Insert the end point in the list
Path.push_back(End);
path.push_back(end);
// The list is done in reverse order and inserted into the path
DijkstraNode::ConstIter CurNode = EndPoint.ParentIter;
while (CurNode != DijkstraNodes.end()) {
BS_ASSERT((*CurNode).Chosen);
Path.push_back(m_Nodes[CurNode - DijkstraNodes.begin()]);
CurNode = (*CurNode).ParentIter;
DijkstraNode::ConstIter curNode = endPoint.parentIter;
while (curNode != dijkstraNodes.end()) {
BS_ASSERT((*curNode).chosen);
path.push_back(_nodes[curNode - dijkstraNodes.begin()]);
curNode = (*curNode).parentIter;
}
// The starting point is inserted into the path
Path.push_back(Start);
path.push_back(start);
// The nodes of the path must be untwisted, as they were extracted in reverse order.
// This step could be saved if the path from end to the beginning was desired
ReverseArray<Vertex>(Path);
ReverseArray<Vertex>(path);
return true;
}
// Relaxation step for nodes of the graph, and perform the end nodes
RelaxNodes(DijkstraNodes, m_VisibilityMatrix, NodeInter);
RelaxEndPoint(m_Nodes[NodeInter - DijkstraNodes.begin()], NodeInter, End, EndPoint, *this);
relaxNodes(dijkstraNodes, _visibilityMatrix, nodeInter);
relaxEndPoint(_nodes[nodeInter - dijkstraNodes.begin()], nodeInter, end, endPoint, *this);
}
// If the loop has been completely run through, all the nodes have been chosen, and still
@ -236,110 +220,101 @@ bool WalkRegion::FindPath(const Vertex &Start, const Vertex &End, BS_Path &Path)
return false;
}
// -----------------------------------------------------------------------------
void WalkRegion::InitNodeVector() {
void WalkRegion::initNodeVector() {
// Empty the Node list
m_Nodes.clear();
_nodes.clear();
// Determine the number of nodes
int NodeCount = 0;
int nodeCount = 0;
{
for (uint i = 0; i < m_Polygons.size(); i++)
NodeCount += m_Polygons[i].VertexCount;
for (uint i = 0; i < _polygons.size(); i++)
nodeCount += _polygons[i].vertexCount;
}
// Knoten-Vector füllen
m_Nodes.reserve(NodeCount);
_nodes.reserve(nodeCount);
{
for (uint j = 0; j < m_Polygons.size(); j++)
for (int i = 0; i < m_Polygons[j].VertexCount; i++)
m_Nodes.push_back(m_Polygons[j].Vertecies[i]);
for (uint j = 0; j < _polygons.size(); j++)
for (int i = 0; i < _polygons[j].vertexCount; i++)
_nodes.push_back(_polygons[j].vertices[i]);
}
}
// -----------------------------------------------------------------------------
void WalkRegion::ComputeVisibilityMatrix() {
void WalkRegion::computeVisibilityMatrix() {
// Initialise visibility matrix
m_VisibilityMatrix = Common::Array< Common::Array <int> >();
for (uint idx = 0; idx < m_Nodes.size(); ++idx) {
_visibilityMatrix = Common::Array< Common::Array <int> >();
for (uint idx = 0; idx < _nodes.size(); ++idx) {
Common::Array<int> arr;
for (uint idx2 = 0; idx2 < m_Nodes.size(); ++idx2)
arr.push_back(infinity);
for (uint idx2 = 0; idx2 < _nodes.size(); ++idx2)
arr.push_back(Infinity);
m_VisibilityMatrix.push_back(arr);
_visibilityMatrix.push_back(arr);
}
// Calculate visibility been vertecies
for (uint j = 0; j < m_Nodes.size(); ++j) {
for (uint i = j; i < m_Nodes.size(); ++i) {
if (IsLineOfSight(m_Nodes[i], m_Nodes[j])) {
for (uint j = 0; j < _nodes.size(); ++j) {
for (uint i = j; i < _nodes.size(); ++i) {
if (isLineOfSight(_nodes[i], _nodes[j])) {
// There is a line of sight, so save the distance between the two
int Distance = m_Nodes[i].Distance(m_Nodes[j]);
m_VisibilityMatrix[i][j] = Distance;
m_VisibilityMatrix[j][i] = Distance;
int distance = _nodes[i].distance(_nodes[j]);
_visibilityMatrix[i][j] = distance;
_visibilityMatrix[j][i] = distance;
} else {
// There is no line of sight, so save infinity as the distance
m_VisibilityMatrix[i][j] = infinity;
m_VisibilityMatrix[j][i] = infinity;
// There is no line of sight, so save Infinity as the distance
_visibilityMatrix[i][j] = Infinity;
_visibilityMatrix[j][i] = Infinity;
}
}
}
}
// -----------------------------------------------------------------------------
bool WalkRegion::CheckAndPrepareStartAndEnd(Vertex &Start, Vertex &End) const {
if (!IsPointInRegion(Start)) {
Vertex NewStart = FindClosestRegionPoint(Start);
bool WalkRegion::checkAndPrepareStartAndEnd(Vertex &start, Vertex &end) const {
if (!isPointInRegion(start)) {
Vertex newStart = findClosestRegionPoint(start);
// Check to make sure the point is really in the region. If not, stop with an error
if (!IsPointInRegion(NewStart)) {
if (!isPointInRegion(newStart)) {
BS_LOG_ERRORLN("Constructed startpoint ((%d,%d) from (%d,%d)) is not inside the region.",
NewStart.X, NewStart.Y,
Start.X, Start.Y);
newStart.x, newStart.y,
start.x, start.y);
return false;
}
Start = NewStart;
start = newStart;
}
// If the destination is outside the region, a point is determined that is within the region,
// and that is used as an endpoint instead
if (!IsPointInRegion(End)) {
Vertex NewEnd = FindClosestRegionPoint(End);
if (!isPointInRegion(end)) {
Vertex newEnd = findClosestRegionPoint(end);
// Make sure that the determined point is really within the region
if (!IsPointInRegion(NewEnd)) {
if (!isPointInRegion(newEnd)) {
BS_LOG_ERRORLN("Constructed endpoint ((%d,%d) from (%d,%d)) is not inside the region.",
NewEnd.X, NewEnd.Y,
End.X, End.Y);
newEnd.x, newEnd.y,
end.x, end.y);
return false;
}
End = NewEnd;
end = newEnd;
}
// Signal success
return true;
}
// -----------------------------------------------------------------------------
void WalkRegion::SetPos(int X, int Y) {
void WalkRegion::setPos(int x, int y) {
// Calculate the difference between old and new position
Vertex Delta(X - m_Position.X, Y - m_Position.Y);
Vertex Delta(x - _position.x, y - _position.y);
// Move all the nodes
for (uint i = 0; i < m_Nodes.size(); i++) m_Nodes[i] += Delta;
for (uint i = 0; i < _nodes.size(); i++)
_nodes[i] += Delta;
// Move regions
Region::SetPos(X, Y);
Region::setPos(x, y);
}
// -----------------------------------------------------------------------------
bool WalkRegion::persist(OutputPersistenceBlock &writer) {
bool result = true;
@ -347,33 +322,31 @@ bool WalkRegion::persist(OutputPersistenceBlock &writer) {
result &= Region::persist(writer);
// Persist the nodes
writer.write(m_Nodes.size());
Common::Array<Vertex>::const_iterator It = m_Nodes.begin();
while (It != m_Nodes.end()) {
writer.write(It->X);
writer.write(It->Y);
++It;
writer.write(_nodes.size());
Common::Array<Vertex>::const_iterator it = _nodes.begin();
while (it != _nodes.end()) {
writer.write(it->x);
writer.write(it->y);
++it;
}
// Persist the visibility matrix
writer.write(m_VisibilityMatrix.size());
Common::Array< Common::Array<int> >::const_iterator RowIter = m_VisibilityMatrix.begin();
while (RowIter != m_VisibilityMatrix.end()) {
writer.write(RowIter->size());
Common::Array<int>::const_iterator ColIter = RowIter->begin();
while (ColIter != RowIter->end()) {
writer.write(*ColIter);
++ColIter;
writer.write(_visibilityMatrix.size());
Common::Array< Common::Array<int> >::const_iterator rowIter = _visibilityMatrix.begin();
while (rowIter != _visibilityMatrix.end()) {
writer.write(rowIter->size());
Common::Array<int>::const_iterator colIter = rowIter->begin();
while (colIter != rowIter->end()) {
writer.write(*colIter);
++colIter;
}
++RowIter;
++rowIter;
}
return result;
}
// -----------------------------------------------------------------------------
bool WalkRegion::unpersist(InputPersistenceBlock &reader) {
bool result = true;
@ -381,34 +354,34 @@ bool WalkRegion::unpersist(InputPersistenceBlock &reader) {
// this point only the additional data from BS_WalkRegion needs to be loaded
// Node load
uint NodeCount;
reader.read(NodeCount);
m_Nodes.clear();
m_Nodes.resize(NodeCount);
Common::Array<Vertex>::iterator It = m_Nodes.begin();
while (It != m_Nodes.end()) {
reader.read(It->X);
reader.read(It->Y);
++It;
uint nodeCount;
reader.read(nodeCount);
_nodes.clear();
_nodes.resize(nodeCount);
Common::Array<Vertex>::iterator it = _nodes.begin();
while (it != _nodes.end()) {
reader.read(it->x);
reader.read(it->y);
++it;
}
// Visibility matrix load
uint RowCount;
reader.read(RowCount);
m_VisibilityMatrix.clear();
m_VisibilityMatrix.resize(RowCount);
Common::Array< Common::Array<int> >::iterator RowIter = m_VisibilityMatrix.begin();
while (RowIter != m_VisibilityMatrix.end()) {
uint ColCount;
reader.read(ColCount);
RowIter->resize(ColCount);
Common::Array<int>::iterator ColIter = RowIter->begin();
while (ColIter != RowIter->end()) {
reader.read(*ColIter);
++ColIter;
uint rowCount;
reader.read(rowCount);
_visibilityMatrix.clear();
_visibilityMatrix.resize(rowCount);
Common::Array< Common::Array<int> >::iterator rowIter = _visibilityMatrix.begin();
while (rowIter != _visibilityMatrix.end()) {
uint colCount;
reader.read(colCount);
rowIter->resize(colCount);
Common::Array<int>::iterator colIter = rowIter->begin();
while (colIter != rowIter->end()) {
reader.read(*colIter);
++colIter;
}
++RowIter;
++rowIter;
}
return result && reader.isGood();

View File

@ -41,16 +41,8 @@
namespace Sword25 {
// -----------------------------------------------------------------------------
// Type definitions
// -----------------------------------------------------------------------------
typedef Common::Array<Vertex> BS_Path;
// -----------------------------------------------------------------------------
// Class definitions
// -----------------------------------------------------------------------------
/**
* This class represents the region in which the main character can move
*/
@ -59,12 +51,12 @@ class WalkRegion : public Region {
protected:
WalkRegion();
WalkRegion(InputPersistenceBlock &Reader, uint Handle);
WalkRegion(InputPersistenceBlock &Reader, uint handle);
public:
virtual ~WalkRegion();
virtual bool Init(const Polygon &Contour, const Common::Array<Polygon> *pHoles = 0);
virtual bool init(const Polygon &contour, const Common::Array<Polygon> *pHoles = 0);
/**
* Get the shortest path between two points in the region
@ -80,8 +72,8 @@ public:
* @param Path An empty BS_Path that will be set to the resulting path
* @return Returns false if the result is invalid, otherwise returns true.
*/
bool QueryPath(int X1, int Y1, int X2, int Y2, BS_Path &Path) {
return QueryPath(Vertex(X1, Y1), Vertex(X2, Y2), Path);
bool queryPath(int x1, int y1, int x2, int y2, BS_Path &path) {
return queryPath(Vertex(x1, y1), Vertex(x2, y2), path);
}
/**
@ -92,28 +84,28 @@ public:
* @param Path An empty BS_Path that will be set to the resulting path
* @return Returns false if the result is invalid, otherwise returns true.
*/
bool QueryPath(Vertex StartPoint, Vertex EndPoint, BS_Path &Path);
bool queryPath(Vertex startPoint, Vertex endPoint, BS_Path &path);
virtual void SetPos(int X, int Y);
virtual void setPos(int x, int y);
const Common::Array<Vertex> &GetNodes() const {
return m_Nodes;
const Common::Array<Vertex> &getNodes() const {
return _nodes;
}
const Common::Array< Common::Array<int> > &GetVisibilityMatrix() const {
return m_VisibilityMatrix;
const Common::Array< Common::Array<int> > &getVisibilityMatrix() const {
return _visibilityMatrix;
}
virtual bool persist(OutputPersistenceBlock &writer);
virtual bool unpersist(InputPersistenceBlock &reader);
private:
Common::Array<Vertex> m_Nodes;
Common::Array< Common::Array<int> > m_VisibilityMatrix;
Common::Array<Vertex> _nodes;
Common::Array< Common::Array<int> > _visibilityMatrix;
void InitNodeVector();
void ComputeVisibilityMatrix();
bool CheckAndPrepareStartAndEnd(Vertex &Start, Vertex &End) const;
bool FindPath(const Vertex &Start, const Vertex &End, BS_Path &Path) const;
void initNodeVector();
void computeVisibilityMatrix();
bool checkAndPrepareStartAndEnd(Vertex &start, Vertex &end) const;
bool findPath(const Vertex &start, const Vertex &end, BS_Path &path) const;
};
} // End of namespace Sword25