2
0
Эх сурвалжийг харах

Improve support for directed graphs in AStar

Shiqing 6 жил өмнө
parent
commit
98136418ac

+ 33 - 20
core/math/a_star.cpp

@@ -164,23 +164,21 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) {
 	}
 	}
 
 
 	Segment s(p_id, p_with_id);
 	Segment s(p_id, p_with_id);
-	if (s.from == p_id) {
-		s.from_point = a;
-		s.to_point = b;
-	} else {
-		s.from_point = b;
-		s.to_point = a;
-	}
-
+	s.from_point = a;
+	s.to_point = b;
 	segments.insert(s);
 	segments.insert(s);
+
+	if (bidirectional) {
+		SWAP(s.from, s.to);
+		SWAP(s.from_point, s.to_point);
+		segments.insert(s);
+	}
 }
 }
 
 
-void AStar::disconnect_points(int p_id, int p_with_id) {
+void AStar::disconnect_points(int p_id, int p_with_id, bool bidirectional) {
 
 
 	Segment s(p_id, p_with_id);
 	Segment s(p_id, p_with_id);
-	ERR_FAIL_COND(!segments.has(s));
-
-	segments.erase(s);
+	Segment t(p_with_id, p_id);
 
 
 	Point *a;
 	Point *a;
 	bool a_exists = points.lookup(p_id, a);
 	bool a_exists = points.lookup(p_id, a);
@@ -190,10 +188,24 @@ void AStar::disconnect_points(int p_id, int p_with_id) {
 	bool b_exists = points.lookup(p_with_id, b);
 	bool b_exists = points.lookup(p_with_id, b);
 	CRASH_COND(!b_exists);
 	CRASH_COND(!b_exists);
 
 
-	a->neighbours.remove(b->id);
-	a->unlinked_neighbours.remove(b->id);
-	b->neighbours.remove(a->id);
-	b->unlinked_neighbours.remove(a->id);
+	bool warned = false;
+
+	if (segments.has(s)) {
+		segments.erase(s);
+		a->neighbours.remove(b->id);
+		b->unlinked_neighbours.remove(a->id);
+	} else {
+		warned = true;
+		WARN_PRINT("The edge to be removed does not exist.");
+	}
+
+	if (bidirectional && segments.has(t)) {
+		segments.erase(t);
+		b->neighbours.remove(a->id);
+		a->unlinked_neighbours.remove(b->id);
+	} else if (bidirectional && !warned) {
+		WARN_PRINT("The reverse edge to be removed does not exist.");
+	}
 }
 }
 
 
 bool AStar::has_point(int p_id) const {
 bool AStar::has_point(int p_id) const {
@@ -227,10 +239,11 @@ PoolVector<int> AStar::get_point_connections(int p_id) {
 	return point_list;
 	return point_list;
 }
 }
 
 
-bool AStar::are_points_connected(int p_id, int p_with_id) const {
+bool AStar::are_points_connected(int p_id, int p_with_id, bool bidirectional) const {
 
 
 	Segment s(p_id, p_with_id);
 	Segment s(p_id, p_with_id);
-	return segments.has(s);
+	Segment t(p_with_id, p_id);
+	return segments.has(s) || (bidirectional && segments.has(t));
 }
 }
 
 
 void AStar::clear() {
 void AStar::clear() {
@@ -532,8 +545,8 @@ void AStar::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar::is_point_disabled);
 	ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar::is_point_disabled);
 
 
 	ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar::connect_points, DEFVAL(true));
 	ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar::connect_points, DEFVAL(true));
-	ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id"), &AStar::disconnect_points);
-	ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id"), &AStar::are_points_connected);
+	ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id", "bidirectional"), &AStar::disconnect_points, DEFVAL(true));
+	ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id", "bidirectional"), &AStar::are_points_connected, DEFVAL(true));
 
 
 	ClassDB::bind_method(D_METHOD("get_point_count"), &AStar::get_point_count);
 	ClassDB::bind_method(D_METHOD("get_point_count"), &AStar::get_point_count);
 	ClassDB::bind_method(D_METHOD("get_point_capacity"), &AStar::get_point_capacity);
 	ClassDB::bind_method(D_METHOD("get_point_capacity"), &AStar::get_point_capacity);

+ 2 - 6
core/math/a_star.h

@@ -93,10 +93,6 @@ class AStar : public Reference {
 		bool operator<(const Segment &p_s) const { return key < p_s.key; }
 		bool operator<(const Segment &p_s) const { return key < p_s.key; }
 		Segment() { key = 0; }
 		Segment() { key = 0; }
 		Segment(int p_from, int p_to) {
 		Segment(int p_from, int p_to) {
-			if (p_from > p_to) {
-				SWAP(p_from, p_to);
-			}
-
 			from = p_from;
 			from = p_from;
 			to = p_to;
 			to = p_to;
 		}
 		}
@@ -133,8 +129,8 @@ public:
 	bool is_point_disabled(int p_id) const;
 	bool is_point_disabled(int p_id) const;
 
 
 	void connect_points(int p_id, int p_with_id, bool bidirectional = true);
 	void connect_points(int p_id, int p_with_id, bool bidirectional = true);
-	void disconnect_points(int p_id, int p_with_id);
-	bool are_points_connected(int p_id, int p_with_id) const;
+	void disconnect_points(int p_id, int p_with_id, bool bidirectional = true);
+	bool are_points_connected(int p_id, int p_with_id, bool bidirectional = true) const;
 
 
 	int get_point_count() const;
 	int get_point_count() const;
 	int get_point_capacity() const;
 	int get_point_capacity() const;