diff --git a/source/blender/blenlib/intern/math_geom.cc b/source/blender/blenlib/intern/math_geom.cc index 09c7b5936e8..e44e1f400dd 100644 --- a/source/blender/blenlib/intern/math_geom.cc +++ b/source/blender/blenlib/intern/math_geom.cc @@ -1517,19 +1517,14 @@ bool isect_point_tri_v2_cw(const float pt[2], int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2]) { - if (line_point_side_v2(v1, v2, pt) >= 0.0f) { - if (line_point_side_v2(v2, v3, pt) >= 0.0f) { - if (line_point_side_v2(v3, v1, pt) >= 0.0f) { - return 1; - } - } + float side12 = line_point_side_v2(v1, v2, pt); + float side23 = line_point_side_v2(v2, v3, pt); + float side31 = line_point_side_v2(v3, v1, pt); + if (side12 >= 0.0f && side23 >= 0.0f && side31 >= 0.0f) { + return 1; } - else { - if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) { - if (!(line_point_side_v2(v3, v1, pt) >= 0.0f)) { - return -1; - } - } + if (side12 <= 0.0f && side23 <= 0.0f && side31 <= 0.0f) { + return -1; } return 0; @@ -1538,25 +1533,16 @@ int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], int isect_point_quad_v2( const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2]) { - if (line_point_side_v2(v1, v2, pt) >= 0.0f) { - if (line_point_side_v2(v2, v3, pt) >= 0.0f) { - if (line_point_side_v2(v3, v4, pt) >= 0.0f) { - if (line_point_side_v2(v4, v1, pt) >= 0.0f) { - return 1; - } - } - } + float side12 = line_point_side_v2(v1, v2, pt); + float side23 = line_point_side_v2(v2, v3, pt); + float side34 = line_point_side_v2(v3, v4, pt); + float side41 = line_point_side_v2(v4, v1, pt); + if (side12 >= 0.0f && side23 >= 0.0f && side34 >= 0.0f && side41 >= 0.0f) { + return 1; } - else { - if (!(line_point_side_v2(v2, v3, pt) >= 0.0f)) { - if (!(line_point_side_v2(v3, v4, pt) >= 0.0f)) { - if (!(line_point_side_v2(v4, v1, pt) >= 0.0f)) { - return -1; - } - } - } + if (side12 <= 0.0f && side23 <= 0.0f && side34 <= 0.0f && side41 <= 0.0f) { + return -1; } - return 0; } diff --git a/source/blender/blenlib/tests/BLI_math_geom_test.cc b/source/blender/blenlib/tests/BLI_math_geom_test.cc index 0b2de4ab9e8..3c3470743c4 100644 --- a/source/blender/blenlib/tests/BLI_math_geom_test.cc +++ b/source/blender/blenlib/tests/BLI_math_geom_test.cc @@ -1,10 +1,13 @@ -/* SPDX-FileCopyrightText: 2023 Blender Authors +/* SPDX-FileCopyrightText: 2024 Blender Authors * * SPDX-License-Identifier: Apache-2.0 */ #include "testing/testing.h" #include "BLI_math_geom.h" +#include "BLI_math_vector_types.hh" + +using namespace blender; TEST(math_geom, DistToLine2DSimple) { @@ -19,3 +22,98 @@ TEST(math_geom, DistToLineSegment2DSimple) float distance = dist_to_line_segment_v2(p, a, b); EXPECT_NEAR(sqrtf(2.0f), distance, 1e-6); } + +#include "BLI_rand.hh" +#include "BLI_timeit.hh" + +TEST(math_geom, IsectPointTri2D) +{ + float2 tri_cw[3] = {{-2, 1}, {4, 4}, {2, -3}}; + float2 tri_ccw[3] = {{-2, 1}, {2, -3}, {4, 4}}; + + float2 inside1{0, 0}; + float2 inside2{2, 2}; + float2 inside3{2, -1}; + float2 inside4{-1, 1}; + EXPECT_EQ(-1, isect_point_tri_v2(inside1, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(+1, isect_point_tri_v2(inside1, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + EXPECT_EQ(-1, isect_point_tri_v2(inside2, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(+1, isect_point_tri_v2(inside2, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + EXPECT_EQ(-1, isect_point_tri_v2(inside3, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(+1, isect_point_tri_v2(inside3, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + EXPECT_EQ(-1, isect_point_tri_v2(inside4, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(+1, isect_point_tri_v2(inside4, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + + float2 outside1{2, 4}; + float2 outside2{-1, -1}; + float2 outside3{0, 3}; + float2 outside4{-4, 0}; + EXPECT_EQ(0, isect_point_tri_v2(outside1, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(0, isect_point_tri_v2(outside1, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + EXPECT_EQ(0, isect_point_tri_v2(outside2, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(0, isect_point_tri_v2(outside2, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + EXPECT_EQ(0, isect_point_tri_v2(outside3, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(0, isect_point_tri_v2(outside3, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + EXPECT_EQ(0, isect_point_tri_v2(outside4, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(0, isect_point_tri_v2(outside4, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + + float2 edge1{0, 2}; + float2 edge2{1, -2}; + EXPECT_EQ(-1, isect_point_tri_v2(edge1, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(+1, isect_point_tri_v2(edge1, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + EXPECT_EQ(-1, isect_point_tri_v2(edge2, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(+1, isect_point_tri_v2(edge2, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + + float2 corner1{4, 4}; + float2 corner2{2, -3}; + EXPECT_EQ(-1, isect_point_tri_v2(corner1, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(+1, isect_point_tri_v2(corner1, tri_ccw[0], tri_ccw[1], tri_ccw[2])); + EXPECT_EQ(-1, isect_point_tri_v2(corner2, tri_cw[0], tri_cw[1], tri_cw[2])); + EXPECT_EQ(+1, isect_point_tri_v2(corner2, tri_ccw[0], tri_ccw[1], tri_ccw[2])); +} + +TEST(math_geom, IsectPointQuad2D) +{ + float2 quad_cw[4] = {{-2, 1}, {4, 4}, {5, 1}, {2, -3}}; + float2 quad_ccw[4] = {{-2, 1}, {2, -3}, {5, 1}, {4, 4}}; + + float2 inside1{0, 0}; + float2 inside2{2, 2}; + float2 inside3{3, -1}; + float2 inside4{-1, 1}; + EXPECT_EQ(-1, isect_point_quad_v2(inside1, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(+1, isect_point_quad_v2(inside1, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + EXPECT_EQ(-1, isect_point_quad_v2(inside2, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(+1, isect_point_quad_v2(inside2, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + EXPECT_EQ(-1, isect_point_quad_v2(inside3, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(+1, isect_point_quad_v2(inside3, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + EXPECT_EQ(-1, isect_point_quad_v2(inside4, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(+1, isect_point_quad_v2(inside4, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + + float2 outside1{2, 4}; + float2 outside2{-1, -1}; + float2 outside3{0, 3}; + float2 outside4{-4, 0}; + EXPECT_EQ(0, isect_point_quad_v2(outside1, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(0, isect_point_quad_v2(outside1, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + EXPECT_EQ(0, isect_point_quad_v2(outside2, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(0, isect_point_quad_v2(outside2, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + EXPECT_EQ(0, isect_point_quad_v2(outside3, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(0, isect_point_quad_v2(outside3, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + EXPECT_EQ(0, isect_point_quad_v2(outside4, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(0, isect_point_quad_v2(outside4, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + + float2 edge1{0, 2}; + float2 edge2{1, -2}; + EXPECT_EQ(-1, isect_point_quad_v2(edge1, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(+1, isect_point_quad_v2(edge1, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + EXPECT_EQ(-1, isect_point_quad_v2(edge2, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(+1, isect_point_quad_v2(edge2, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + + float2 corner1{4, 4}; + float2 corner2{2, -3}; + EXPECT_EQ(-1, isect_point_quad_v2(corner1, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(+1, isect_point_quad_v2(corner1, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); + EXPECT_EQ(-1, isect_point_quad_v2(corner2, quad_cw[0], quad_cw[1], quad_cw[2], quad_cw[3])); + EXPECT_EQ(+1, isect_point_quad_v2(corner2, quad_ccw[0], quad_ccw[1], quad_ccw[2], quad_ccw[3])); +}