mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
SWORD25: Enforced code naming conventions in math/*
svn-id: r53392
This commit is contained in:
parent
54ccc8f4c9
commit
063cb5d84c
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.");
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
virtual ~Geometry() {}
|
||||
|
||||
private:
|
||||
bool _RegisterScriptBindings();
|
||||
bool registerScriptBindings();
|
||||
};
|
||||
|
||||
} // End of namespace Sword25
|
||||
|
@ -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 ®ion, 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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ®ion,
|
||||
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 ®ion) {
|
||||
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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user