| 
									
										
										
										
											2018-08-29 22:38:13 +02:00
										 |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-05-11 14:36:46 +02:00
										 |  |  | /*  delaunay_2d.h                                                         */ | 
					
						
							| 
									
										
										
										
											2018-08-29 22:38:13 +02:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the        */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including    */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
					
						
							|  |  |  | /* the following conditions:                                              */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be         */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.        */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-11 14:36:46 +02:00
										 |  |  | #ifndef DELAUNAY_2D_H
 | 
					
						
							|  |  |  | #define DELAUNAY_2D_H
 | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/math/rect2.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-04 15:35:14 +01:00
										 |  |  | #include "core/templates/vector.h"
 | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Delaunay2D { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 	struct Triangle { | 
					
						
							|  |  |  | 		int points[3]; | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		Vector2 circum_center; | 
					
						
							|  |  |  | 		real_t circum_radius_squared; | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 		Triangle() {} | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 		Triangle(int p_a, int p_b, int p_c) { | 
					
						
							|  |  |  | 			points[0] = p_a; | 
					
						
							|  |  |  | 			points[1] = p_b; | 
					
						
							|  |  |  | 			points[2] = p_c; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct Edge { | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		int points[2]; | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 		bool bad = false; | 
					
						
							|  |  |  | 		Edge() {} | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 		Edge(int p_a, int p_b) { | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 			// Store indices in a sorted manner to avoid having to check both orientations later.
 | 
					
						
							|  |  |  | 			if (p_a > p_b) { | 
					
						
							|  |  |  | 				points[0] = p_b; | 
					
						
							|  |  |  | 				points[1] = p_a; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				points[0] = p_a; | 
					
						
							|  |  |  | 				points[1] = p_b; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-17 23:24:59 +01:00
										 |  |  | 	static Triangle create_triangle(const Vector<Vector2> &p_vertices, int p_a, int p_b, int p_c) { | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		Triangle triangle = Triangle(p_a, p_b, p_c); | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		// Get the values of the circumcircle and store them inside the triangle object.
 | 
					
						
							|  |  |  | 		Vector2 a = p_vertices[p_b] - p_vertices[p_a]; | 
					
						
							|  |  |  | 		Vector2 b = p_vertices[p_c] - p_vertices[p_a]; | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		Vector2 O = (b * a.length_squared() - a * b.length_squared()).orthogonal() / (a.cross(b) * 2.0f); | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		triangle.circum_radius_squared = O.length_squared(); | 
					
						
							|  |  |  | 		triangle.circum_center = O + p_vertices[p_a]; | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		return triangle; | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static Vector<Triangle> triangulate(const Vector<Vector2> &p_points) { | 
					
						
							|  |  |  | 		Vector<Vector2> points = p_points; | 
					
						
							|  |  |  | 		Vector<Triangle> triangles; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		int point_count = p_points.size(); | 
					
						
							|  |  |  | 		if (point_count <= 2) { | 
					
						
							|  |  |  | 			return triangles; | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		// Get a bounding rectangle.
 | 
					
						
							|  |  |  | 		Rect2 rect = Rect2(p_points[0], Size2()); | 
					
						
							|  |  |  | 		for (int i = 1; i < point_count; i++) { | 
					
						
							|  |  |  | 			rect.expand_to(p_points[i]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		real_t delta_max = MAX(rect.size.width, rect.size.height); | 
					
						
							| 
									
										
										
										
											2021-09-21 00:33:52 +05:45
										 |  |  | 		Vector2 center = rect.get_center(); | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		// Construct a bounding triangle around the rectangle.
 | 
					
						
							|  |  |  | 		points.push_back(Vector2(center.x - delta_max * 16, center.y - delta_max)); | 
					
						
							|  |  |  | 		points.push_back(Vector2(center.x, center.y + delta_max * 16)); | 
					
						
							|  |  |  | 		points.push_back(Vector2(center.x + delta_max * 16, center.y - delta_max)); | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		Triangle bounding_triangle = create_triangle(points, point_count + 0, point_count + 1, point_count + 2); | 
					
						
							|  |  |  | 		triangles.push_back(bounding_triangle); | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		for (int i = 0; i < point_count; i++) { | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 			Vector<Edge> polygon; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 			// Save the edges of the triangles whose circumcircles contain the i-th vertex. Delete the triangles themselves.
 | 
					
						
							|  |  |  | 			for (int j = triangles.size() - 1; j >= 0; j--) { | 
					
						
							|  |  |  | 				if (points[i].distance_squared_to(triangles[j].circum_center) < triangles[j].circum_radius_squared) { | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 					polygon.push_back(Edge(triangles[j].points[0], triangles[j].points[1])); | 
					
						
							|  |  |  | 					polygon.push_back(Edge(triangles[j].points[1], triangles[j].points[2])); | 
					
						
							|  |  |  | 					polygon.push_back(Edge(triangles[j].points[2], triangles[j].points[0])); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 					triangles.remove_at(j); | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 			// Create a triangle for every unique edge.
 | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 			for (int j = 0; j < polygon.size(); j++) { | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 				if (polygon[j].bad) { | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 				for (int k = j + 1; k < polygon.size(); k++) { | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 					// Compare the edges.
 | 
					
						
							|  |  |  | 					if (polygon[k].points[0] == polygon[j].points[0] && polygon[k].points[1] == polygon[j].points[1]) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 						polygon.write[j].bad = true; | 
					
						
							|  |  |  | 						polygon.write[k].bad = true; | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						break; // Since no more than two triangles can share an edge, no more than two edges can share vertices.
 | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 				// Create triangles out of good edges.
 | 
					
						
							|  |  |  | 				if (!polygon[j].bad) { | 
					
						
							|  |  |  | 					triangles.push_back(create_triangle(points, polygon[j].points[0], polygon[j].points[1], i)); | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		// Filter out the triangles containing vertices of the bounding triangle.
 | 
					
						
							|  |  |  | 		int preserved_count = 0; | 
					
						
							|  |  |  | 		Triangle *triangles_ptrw = triangles.ptrw(); | 
					
						
							| 
									
										
										
										
											2023-06-17 11:18:30 -04:00
										 |  |  | 		for (int i = 0; i < triangles.size(); i++) { | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 			if (!(triangles[i].points[0] >= point_count || triangles[i].points[1] >= point_count || triangles[i].points[2] >= point_count)) { | 
					
						
							|  |  |  | 				triangles_ptrw[preserved_count] = triangles[i]; | 
					
						
							|  |  |  | 				preserved_count++; | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-04-08 02:46:24 +02:00
										 |  |  | 		triangles.resize(preserved_count); | 
					
						
							| 
									
										
										
										
											2018-06-21 22:48:47 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return triangles; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-11 14:36:46 +02:00
										 |  |  | #endif // DELAUNAY_2D_H
 |