Skip to content

Commit

Permalink
Merge pull request #1576 from n0099/patch-3
Browse files Browse the repository at this point in the history
add a missing constructor for struct `RotatedRect` from three vertex points
  • Loading branch information
shimat authored Jun 5, 2023
2 parents 117600e + f725f6a commit c55dcd5
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
44 changes: 43 additions & 1 deletion src/OpenCvSharp/Modules/core/Struct/RotatedRect.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;

Expand Down Expand Up @@ -39,6 +40,47 @@ public RotatedRect(Point2f center, Size2f size, float angle)
Angle = angle;
}

/// <summary>
/// Any 3 end points of the RotatedRect. They must be given in order (either clockwise or anticlockwise).
/// </summary>
public RotatedRect(Point2f point1, Point2f point2, Point2f point3)
{ // https://github.com/opencv/opencv/blob/6ad77b23193bdf7e40db83e6077789284ac08781/modules/core/src/types.cpp#LL147C20-L147C20
var center = (point1 + point3) * 0.5;
var vecs = new Vec2f[2];
vecs[0] = (point1 - point2).ToVec2f();
vecs[1] = (point2 - point3).ToVec2f();
var x = Math.Max(Cv2.Norm(point1.ToVec2f()), Math.Max(Cv2.Norm(point2.ToVec2f()), Cv2.Norm(point3.ToVec2f())));
var a = Math.Min(Cv2.Norm(vecs[0]), Cv2.Norm(vecs[1]));

const float fltEpsilon = 1.19209290e-7f; // https://github.com/opencv/opencv/blob/6ad77b23193bdf7e40db83e6077789284ac08781/modules/dnn/src/math_utils.hpp#L39
static double Ddot(Vec2f a, Vec2f b)
{ // https://github.com/opencv/opencv/blob/0052d46b8e33c7bfe0e1450e4bff28b88f455570/modules/core/include/opencv2/core/matx.hpp#L741
var s = 0d;
for (var i = 0; i < 2; i++)
{
s += (double)a[i] * b[i];
}
return s;
}
// check that given sides are perpendicular
Debug.Assert(Math.Abs(Ddot(vecs[0], vecs[1])) * a <= fltEpsilon * 9 * x * (Cv2.Norm(vecs[0]) * Cv2.Norm(vecs[1])));

// wd_i stores which vector (0,1) or (1,2) will make the width
// One of them will definitely have slope within -1 to 1
var wdI = 0;
if (Math.Abs(vecs[1][1]) < Math.Abs(vecs[1][0]))
{
wdI = 1;
}
var htI = (wdI + 1) % 2;

var angle = Math.Atan(vecs[wdI][1] / vecs[wdI][0]) * 180.0f / (float)Math.PI;
var width = (float)Cv2.Norm(vecs[wdI]);
var height = (float)Cv2.Norm(vecs[htI]);

return new(center, new(width, height), (float)angle);
}

/// <summary>
/// returns 4 vertices of the rectangle
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions test/OpenCvSharp.Tests/OpenCvSharp.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net48</TargetFrameworks>
Expand All @@ -10,7 +10,7 @@
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<LangVersion>10</LangVersion>
<LangVersion>11</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>

Expand Down

0 comments on commit c55dcd5

Please sign in to comment.