Browse Source

Merge pull request #15943 from poke1024/geometry-line-line

Add Geometry::line_intersects_line_2d()
Juan Linietsky 7 years ago
parent
commit
69a96ff4a6
4 changed files with 42 additions and 0 deletions
  1. 11 0
      core/bind/core_bind.cpp
  2. 1 0
      core/bind/core_bind.h
  3. 15 0
      core/math/geometry.h
  4. 15 0
      doc/classes/Geometry.xml

+ 11 - 0
core/bind/core_bind.cpp

@@ -1281,6 +1281,16 @@ Variant _Geometry::segment_intersects_segment_2d(const Vector2 &p_from_a, const
 	};
 };
 
+Variant _Geometry::line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) {
+
+	Vector2 result;
+	if (Geometry::line_intersects_line_2d(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) {
+		return result;
+	} else {
+		return Variant();
+	}
+}
+
 PoolVector<Vector2> _Geometry::get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) {
 
 	Vector2 r1, r2;
@@ -1436,6 +1446,7 @@ void _Geometry::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("build_capsule_planes", "radius", "height", "sides", "lats", "axis"), &_Geometry::build_capsule_planes, DEFVAL(Vector3::AXIS_Z));
 	ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &_Geometry::segment_intersects_circle);
 	ClassDB::bind_method(D_METHOD("segment_intersects_segment_2d", "from_a", "to_a", "from_b", "to_b"), &_Geometry::segment_intersects_segment_2d);
+	ClassDB::bind_method(D_METHOD("line_intersects_line_2d", "from_a", "dir_a", "from_b", "dir_b"), &_Geometry::line_intersects_line_2d);
 
 	ClassDB::bind_method(D_METHOD("get_closest_points_between_segments_2d", "p1", "q1", "p2", "q2"), &_Geometry::get_closest_points_between_segments_2d);
 	ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "p2", "q1", "q2"), &_Geometry::get_closest_points_between_segments);

+ 1 - 0
core/bind/core_bind.h

@@ -358,6 +358,7 @@ public:
 	PoolVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
 	PoolVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
 	Variant segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
+	Variant line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b);
 	PoolVector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
 	PoolVector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2);
 	Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);

+ 15 - 0
core/math/geometry.h

@@ -529,6 +529,21 @@ public:
 		return p_segment[0] + n * d; // inside
 	}
 
+	static bool line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b, Vector2 &r_result) {
+
+		// see http://paulbourke.net/geometry/pointlineplane/
+
+		const real_t denom = p_dir_b.y * p_dir_a.x - p_dir_b.x * p_dir_a.y;
+		if (Math::abs(denom) < CMP_EPSILON) { // parallel?
+			return false;
+		}
+
+		const Vector2 v = p_from_a - p_from_b;
+		const real_t t = (p_dir_b.x * v.y - p_dir_b.y * v.x) / denom;
+		r_result = p_from_a + t * p_dir_a;
+		return true;
+	}
+
 	static bool segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b, Vector2 *r_result) {
 
 		Vector2 B = p_to_a - p_from_a;

+ 15 - 0
doc/classes/Geometry.xml

@@ -259,6 +259,21 @@
 				Checks if the two segments ([code]from_a[/code], [code]to_a[/code]) and ([code]from_b[/code], [code]to_b[/code]) intersect. If yes, return the point of intersection as [Vector2]. If no intersection takes place, returns an empty [Variant].
 			</description>
 		</method>
+		<method name="line_intersects_line_2d">
+			<return type="Variant">
+			</return>
+			<argument index="0" name="from_a" type="Vector2">
+			</argument>
+			<argument index="1" name="dir_a" type="Vector2">
+			</argument>
+			<argument index="2" name="from_b" type="Vector2">
+			</argument>
+			<argument index="3" name="dir_b" type="Vector2">
+			</argument>
+			<description>
+				Checks if the two lines ([code]from_a[/code], [code]dir_a[/code]) and ([code]from_b[/code], [code]dir_b[/code]) intersect. If yes, return the point of intersection as [Vector2]. If no intersection takes place, returns an empty [Variant]. Note that the lines are specified using direction vectors, not end points.
+			</description>
+		</method>
 		<method name="segment_intersects_sphere">
 			<return type="PoolVector3Array">
 			</return>