[Scummvm-cvs-logs] SF.net SVN: scummvm:[39544] scummvm/trunk/engines/sci/engine

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Thu Mar 19 23:47:31 CET 2009


Revision: 39544
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39544&view=rev
Author:   waltervn
Date:     2009-03-19 22:47:30 +0000 (Thu, 19 Mar 2009)

Log Message:
-----------
SCI: converted aatree into a class

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/aatree.h
    scummvm/trunk/engines/sci/engine/kpathing.cpp

Removed Paths:
-------------
    scummvm/trunk/engines/sci/engine/aatree.cpp

Deleted: scummvm/trunk/engines/sci/engine/aatree.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/aatree.cpp	2009-03-19 22:06:46 UTC (rev 39543)
+++ scummvm/trunk/engines/sci/engine/aatree.cpp	2009-03-19 22:47:30 UTC (rev 39544)
@@ -1,162 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "sci/engine/aatree.h"
-
-#include "sci/sci_memory.h"
-
-namespace Sci {
-
-struct aatree {
-	struct aatree *left, *right;
-	int level;
-	void *key;
-};
-
-// Sentinel node
-static aatree_t bottom = {&bottom, &bottom, 0, NULL};
-
-static void skew(aatree_t **t) {
-	if ((*t)->left->level == (*t)->level) {
-		// Rotate right
-		aatree_t *temp = *t;
-		*t = (*t)->left;
-		temp->left = (*t)->right;
-		(*t)->right = temp;
-	}
-}
-
-static void split(aatree_t **t) {
-	if ((*t)->right->right->level == (*t)->level) {
-		// Rotate left
-		aatree_t *temp = *t;
-		*t = (*t)->right;
-		temp->right = (*t)->left;
-		(*t)->left = temp;
-		(*t)->level++;
-	}
-}
-
-static int delete_node(void *x, aatree_t **t, aatree_t *deleted, int (*compar)(const void *, const void *)) {
-	int retval = -1;
-
-	if (*t != &bottom) {
-		// Search down the tree
-		aatree_t **n;
-
-		if (compar(x, (*t)->key) < 0)
-			n = &(*t)->left;
-		else {
-			n = &(*t)->right;
-			deleted = *t;
-		}
-
-		retval = delete_node(x, n, deleted, compar);
-
-		// At the bottom of the tree we remove the element (if it is present)
-		if ((*n == &bottom) && (deleted != &bottom) && (compar(x, deleted->key) == 0)) {
-			aatree_t *temp;
-			deleted->key = (*t)->key;
-			temp = *t;
-			*t = (*t)->right;
-			free(temp);
-			retval = 0;
-		} else if (((*t)->left->level < (*t)->level - 1) || ((*t)->right->level < (*t)->level - 1)) {
-			(*t)->level--;
-			if ((*t)->right->level > (*t)->level)
-				(*t)->right->level = (*t)->level;
-			skew(t);
-			skew(&(*t)->right);
-			skew(&(*t)->right->right);
-			split(t);
-			split(&(*t)->right);
-		}
-	}
-
-	return retval;
-}
-
-aatree_t *aatree_new() {
-	return ⊥
-}
-
-int aatree_insert(void *x, aatree_t **t, int (*compar)(const void *, const void *)) {
-	int retval = -1;
-	int c;
-
-	if (*t == &bottom) {
-		*t = (aatree_t *)sci_malloc(sizeof(aatree_t));
-
-		if (*t == NULL)
-			return 1;
-
-		(*t)->key = x;
-		(*t)->left = ⊥
-		(*t)->right = ⊥
-		(*t)->level = 1;
-		return 0;
-	}
-
-	c = compar(x, (*t)->key);
-
-	if (c < 0)
-		retval = aatree_insert(x, &(*t)->left, compar);
-	else if (c > 0)
-		retval = aatree_insert(x, &(*t)->right, compar);
-
-	skew(t);
-	split(t);
-	return retval;
-}
-
-int aatree_delete(void *x, aatree_t **t, int (*compar)(const void *, const void *)) {
-	return delete_node(x, t, &bottom, compar);
-}
-
-aatree_t *aatree_walk(aatree_t *t, int direction) {
-	if ((direction == AATREE_WALK_LEFT) && (t->left != &bottom))
-		return t->left;
-
-	if ((direction == AATREE_WALK_RIGHT) && (t->right != &bottom))
-		return t->right;
-
-	return NULL;
-}
-
-void *aatree_get_data(aatree_t *t) {
-	return t->key;
-}
-
-void aatree_free(aatree_t *t) {
-	if (t == &bottom)
-		return;
-
-	aatree_free(t->left);
-	aatree_free(t->right);
-
-	free(t);
-}
-
-} // End of namespace Sci

Modified: scummvm/trunk/engines/sci/engine/aatree.h
===================================================================
--- scummvm/trunk/engines/sci/engine/aatree.h	2009-03-19 22:06:46 UTC (rev 39543)
+++ scummvm/trunk/engines/sci/engine/aatree.h	2009-03-19 22:47:30 UTC (rev 39544)
@@ -26,62 +26,173 @@
 #ifndef SCI_ENGINE_AATREE_H
 #define SCI_ENGINE_AATREE_H
 
+#include "common/func.h"
+
 namespace Sci {
 
-/* Andersson tree implementation. Stores data pointers in a balanced binary
-** tree. A user-supplied comparison function defines the ordering. For the
-** semantics of this function see qsort(3)
-*/
+// Andersson tree implementation.
 
-typedef struct aatree aatree_t;
+template<typename Key>
+struct AATreeNode {
+	AATreeNode() : _left(this), _right(this), _level(0) { }
+	AATreeNode(const Key &key, AATreeNode *left, AATreeNode *right, int level) : _key(key), _left(left), _right(right), _level(level) { }
 
-// Left child
-#define AATREE_WALK_LEFT 0
-// Right child
-#define AATREE_WALK_RIGHT 1
+	Key _key;
+	AATreeNode *_left, *_right;
+	int _level;
+};
 
-aatree_t *aatree_new();
-/* Allocates a new aatree
-** Parameters: (void)
-** Returns   : (aatree_t *) A newly allocated aatree
-*/
+template<typename Key, class LessFunc = Common::Less<Key> >
+class AATree {
+public:
+	AATree() {
+		_bottom = new AATreeNode<Key>;
+		_root = _bottom;
+	}
 
-void aatree_free(aatree_t *t);
-/* Deallocates an aatree
-** Parameters: (aatree_t *) t: The aatree
-** Returns   : (void)
-*/
+	AATree(const AATree<Key, LessFunc> &tree) {
+		_bottom = new AATreeNode<Key>;
+		_root = copyTree(tree._root, tree._bottom);
+	}
 
-int aatree_delete(void *x, aatree_t **t, int (*compar)(const void *, const void *));
-/* Deletes a data element from an aatree
-** Parameters: (void *) x: The data element to delete
-**             (aatree_t **) t: The aatree
-**             compar: The comparison function
-** Returns   : (int) 0 on success, -1 if x wasn't found in t
-*/
+	const AATree<Key, LessFunc> &operator=(const AATree<Key, LessFunc> &tree) {
+		if (this != &tree) {
+			freeNode(_root);
+			_root = copyTree(tree._root, tree._bottom);
+		}
 
-int aatree_insert(void *x, aatree_t **t, int (*compar)(const void *, const void *));
-/* Inserts a data element into an aatree
-** Parameters: (void *) x: The data element to insert
-**             (aatree_t **) t: The aatree
-**             compar: The comparison function
-** Returns   : (int) 0 on success, -1 if x already exists in t
-*/
+		return *this;
+	}
 
-aatree_t *aatree_walk(aatree_t *t, int direction);
-/* Walks to either the left or right child of a node
-** Parameters: (aatree_t *) t: The node
-**             (int) direction: AATREE_WALK_LEFT or AATREE_WALK_RIGHT
-** Returns   : (aatree_t *) The requested child of t or NULL if it doesn't
-**                          exist
-*/
+	~AATree() {
+		freeNode(_root);
+		delete _bottom;
+	}
 
-void *aatree_get_data(aatree_t *t);
-/* Returns the data element of a node
-** Parameters: (aatree_t *) t: The node
-** Returns   : (void *) The data element
-*/
+	void insert(const Key &key) {
+		insertNode(key, _root);
+	}
 
+	bool remove(const Key &key) {
+		return removeNode(key, _root);
+	}
+
+	// Returns a pointer to the smallest Key or NULL if the tree is empty.
+	const Key *findSmallest() {
+		AATreeNode<Key> *node = _root;
+
+		if (node == _bottom)
+			return NULL;
+
+		while (node->_left != _bottom)
+			node = node->_left;
+
+		return &node->_key;
+	}
+
+private:
+	AATreeNode<Key> *_root;
+	AATreeNode<Key> *_bottom;
+	LessFunc _less;
+
+private:
+	void freeNode(AATreeNode<Key> *node) {
+		if (node == _bottom)
+			return;
+
+		freeNode(node->_left);
+		freeNode(node->_right);
+
+		delete node;
+	}
+
+	void skew(AATreeNode<Key> *&node) {
+		if (node->_left->_level == node->_level) {
+			// Rotate right
+			AATreeNode<Key> *temp = node;
+			node = node->_left;
+			temp->_left = node->_right;
+			node->_right = temp;
+		}
+	}
+
+	void split(AATreeNode<Key> *&node) {
+		if (node->_right->_right->_level == node->_level) {
+			// Rotate left
+			AATreeNode<Key> *temp = node;
+			node = node->_right;
+			temp->_right = node->_left;
+			node->_left = temp;
+			node->_level++;
+		}
+	}
+
+	bool removeNode(const Key &key, AATreeNode<Key> *&node) {
+		bool ok = false;
+		static AATreeNode<Key> *last, *deleted = _bottom;
+
+		if (node != _bottom) {
+			// Search down the tree and set pointers last and deleted
+			last = node;
+
+			if (_less(key, node->_key))
+				ok = removeNode(key, node->_left);
+			else {
+				deleted = node;
+				ok = removeNode(key, node->_right);
+			}
+
+			if ((node == last) && (deleted != _bottom) && !_less(key, deleted->_key) && !_less(deleted->_key, key)) {
+				// At the bottom of the tree we remove the element (if it is present)
+				deleted->_key = node->_key;
+				deleted = _bottom;
+				node = node->_right;
+				delete last;
+				return true;
+			}
+
+			if ((node->_left->_level < node->_level - 1) || (node->_right->_level < node->_level - 1)) {
+				// On the way back, we rebalance
+				node->_level--;
+				if (node->_right->_level > node->_level)
+					node->_right->_level = node->_level;
+
+				skew(node);
+				skew(node->_right);
+				skew(node->_right->_right);
+				split(node);
+				split(node->_right);
+			}
+		}
+
+		return ok;
+	}
+
+	void insertNode(const Key &key, AATreeNode<Key> *&node) {
+		if (node == _bottom) {
+			node = new AATreeNode<Key>(key, _bottom, _bottom, 1);
+
+			assert(node);
+			return;
+		}
+
+		if (_less(key, node->_key))
+			insertNode(key, node->_left);
+		else if (_less(node->_key, key))
+			insertNode(key, node->_right);
+
+		skew(node);
+		split(node);
+	}
+
+	AATreeNode<Key> *copyTree(AATreeNode<Key> *node, const AATreeNode<Key> *bottom) {
+		if (node == bottom)
+			return _bottom;
+
+		return new AATreeNode<Key>(node->_key, copyTree(node->_left, bottom), copyTree(node->_right, bottom), node->_level);
+	}
+};
+
 } // End of namespace Sci
 
 #endif // SCI_ENIGNE_AATREE_H

Modified: scummvm/trunk/engines/sci/engine/kpathing.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kpathing.cpp	2009-03-19 22:06:46 UTC (rev 39543)
+++ scummvm/trunk/engines/sci/engine/kpathing.cpp	2009-03-19 22:47:30 UTC (rev 39544)
@@ -644,10 +644,10 @@
 	return -1;
 }
 
-static void clockwise(Vertex *v, Common::Point *p1, Common::Point *p2) {
+static void clockwise(const Vertex *v, Common::Point *p1, Common::Point *p2) {
 	// Orders the points of an edge clockwise around vertex_cur. If all three
 	// points are collinear the original order is used
-	// Parameters: (Vertex *) v: The first vertex of the edge
+	// Parameters: (const Vertex *) v: The first vertex of the edge
 	// Returns   : (void)
 	//             (Common::Point) *p1: The first point in clockwise order
 	//             (Common::Point) *p2: The second point in clockwise order
@@ -662,46 +662,34 @@
 	}
 }
 
-static int edge_compare(const void *a, const void *b) {
+struct EdgeIsCloser: public Common::BinaryFunction<const Vertex *, const Vertex *, bool> {
 	// Compares two edges that are intersected by the sweeping line by distance
 	// from vertex_cur
-	// Parameters: (const void *) a, b: The first vertices of the edges
-	// Returns   : (int) -1 if a is closer than b, 1 if b is closer than a, and
-	//                   0 if a and b are equal
-	Common::Point v1, v2, w1, w2;
+	// Parameters: (const Vertex *const &) a, b: The first vertices of the edges
+	// Returns   : (bool) true if a is closer to vertex_cur than b, false otherwise
+	bool operator()(const Vertex *const &a, const Vertex *const &b) const {
+		Common::Point v1, v2, w1, w2;
 
-	// We can assume that the sweeping line intersects both edges and
-	// that the edges do not properly intersect
+		// Check for comparison of the same edge
+		if (a == b)
+			return false;
 
-	if (a == b)
-		return 0;
+		// We can assume that the sweeping line intersects both edges and
+		// that the edges do not properly intersect
 
-	// Order vertices clockwise so we know vertex_cur is to the right of
-	// directed edges (v1, v2) and (w1, w2)
-	clockwise((Vertex *)a, &v1, &v2);
-	clockwise((Vertex *)b, &w1, &w2);
+		// Order vertices clockwise so we know vertex_cur is to the right of
+		// directed edges (v1, v2) and (w1, w2)
+		clockwise(a, &v1, &v2);
+		clockwise(b, &w1, &w2);
 
-	// As the edges do not properly intersect one edge must lie entirely
-	// to one side of another. Note that the special case where edges are
-	// collinear does not need to be handled as those edges will never be
-	// in the tree simultaneously
+		// At this point we know that one edge must lie entirely to one side
+		// of the other, as the edges are not collinear and cannot intersect
+		// other than possibly sharing a vertex.
 
-	// b is left of a
-	if (left_on(v1, v2, w1) && left_on(v1, v2, w2))
-		return -1;
+		return ((left_on(v1, v2, w1) && left_on(v1, v2, w2)) || (left_on(w2, w1, v1) && left_on(w2, w1, v2)));
+	}
+};
 
-	// b is right of a
-	if (left_on(v2, v1, w1) && left_on(v2, v1, w2))
-		return 1;
-
-	// a is left of b
-	if (left_on(w1, w2, v1) && left_on(w1, w2, v2))
-		return 1;
-
-	// a is right of b
-	return -1;
-}
-
 static int inside(Common::Point p, Vertex *vertex) {
 	// Determines whether or not a line from a point to a vertex intersects the
 	// interior of the polygon, locally at that vertex
@@ -731,19 +719,20 @@
 	return 0;
 }
 
-static int visible(Vertex *vertex, Vertex *vertex_prev, int visible, aatree_t *tree) {
+typedef AATree<const Vertex *, EdgeIsCloser> EdgeAATree;
+
+static int visible(Vertex *vertex, Vertex *vertex_prev, int visible, EdgeAATree &tree) {
 	// Determines whether or not a vertex is visible from vertex_cur
 	// Parameters: (Vertex *) vertex: The vertex
 	//             (Vertex *) vertex_prev: The previous vertex in the sort
 	//                                       order, or NULL
 	//             (int) visible: 1 if vertex_prev is visible, 0 otherwise
-	//             (aatree_t *) tree: The tree of edges intersected by the
-	//                                sweeping line
+	//             (EdgeAATree &) tree: The tree of edges intersected by the
+	//                                  sweeping line
 	// Returns   : (int) 1 if vertex is visible from vertex_cur, 0 otherwise
-	Vertex *edge;
+	const Vertex *const *edge;
 	Common::Point p = vertex_cur->v;
 	Common::Point w = vertex->v;
-	aatree_t *tree_n = tree;
 
 	// Check if sweeping line intersects the interior of the polygon
 	// locally at vertex
@@ -755,17 +744,13 @@
 	if (vertex_prev && !visible && between(p, w, vertex_prev->v))
 		return 0;
 
-	// Find leftmost node of tree */
-	while ((tree_n = aatree_walk(tree_n, AATREE_WALK_LEFT)))
-		tree = tree_n;
+	edge = tree.findSmallest();
 
-	edge = (Vertex*)aatree_get_data(tree);
-
 	if (edge) {
 		Common::Point p1, p2;
 
 		// Check for intersection with sweeping line before vertex
-		clockwise(edge, &p1, &p2);
+		clockwise(*edge, &p1, &p2);
 		if (left(p2, p1, p) && left(p1, p2, w))
 			return 0;
 	}
@@ -778,7 +763,7 @@
 	// updates the visibility matrix
 	// Parameters: (PathfindingState *) s: The pathfinding state
 	//             (Vertex *) vert: The vertex
-	aatree_t *tree = aatree_new();
+	EdgeAATree tree;
 	Common::Point p = vert->v;
 	Polygon *polygon;
 	int i;
@@ -804,7 +789,7 @@
 			clockwise(vertex, &high, &low);
 
 			if ((high.y < p.y) && (low.y >= p.y) && (low != p))
-				aatree_insert(vertex, &tree, edge_compare);
+				tree.insert(vertex);
 		}
 	}
 
@@ -824,13 +809,13 @@
 		// Delete anti-clockwise edges from tree
 		v1 = CLIST_PREV(vert_sorted[i]);
 		if (left(p, vert_sorted[i]->v, v1->v)) {
-			if (aatree_delete(v1, &tree, edge_compare))
+			if (!tree.remove(v1))
 				sciprintf("[avoidpath] Error: failed to remove edge from tree\n");
 		}
 
 		v1 = CLIST_NEXT(vert_sorted[i]);
 		if (left(p, vert_sorted[i]->v, v1->v)) {
-			if (aatree_delete(vert_sorted[i], &tree, edge_compare))
+			if (!tree.remove(vert_sorted[i]))
 				sciprintf("[avoidpath] Error: failed to remove edge from tree\n");
 		}
 
@@ -840,19 +825,16 @@
 			for (j = i; (j >= 1) && collinear(p, vert_sorted[i]->v, vert_sorted[j]->v); j--) {
 				v1 = CLIST_PREV(vert_sorted[j]);
 				if (left(vert_sorted[j]->v, p, v1->v))
-					aatree_insert(v1, &tree, edge_compare);
+					tree.insert(v1);
 
 				v1 = CLIST_NEXT(vert_sorted[j]);
 				if (left(vert_sorted[j]->v, p, v1->v))
-					aatree_insert(vert_sorted[j], &tree, edge_compare);
+					tree.insert(vert_sorted[j]);
 			}
 		}
 	}
 
 	free(vert_sorted);
-
-	// Free tree
-	aatree_free(tree);
 }
 
 static float distance(FloatPoint a, FloatPoint b) {


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list