360度旋转直线绘制
顺时针0~360度旋转直线绘制,主要用于计算各种直线角度算法的验证与测试。
执行结果如下:
图中红色长线是绘制起点,绿线是终点,间隔角度为1度。

C++版本如下:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <fstream>
#include <string>
#include <vector>
using namespace cv;
using namespace std;
vector<Vec4i> DrawArc(Point Center, Point Start)
{
vector<Vec4i> lines;
vector<Point> Dots;
int brim = floor(360 / 1);
Dots.push_back(Start);
for (int i = 0; i < brim - 1; i++)
{
double dSinRot = sin(-(1 * (i + 1)) * CV_PI / 180);
double dCosRot = cos(-(1 * (i + 1)) * CV_PI / 180);
double x = Center.x + dCosRot * (double)(Start.x - Center.x) - dSinRot * (double)(Start.y - Center.y);
double y = Center.y + dSinRot * (double)(Start.x - Center.x) + dCosRot * (double)(Start.y - Center.y);
Dots.push_back(Point((int)x, (int)y));
}
for (int i = 0; i < Dots.size(); i++) {
lines.push_back(Vec4i(Center.x, Center.y, Dots[i].x, Dots[i].y));
}
Dots.clear();
return lines;
}
// 计算顺时针角度:0~360
float VectorLine(Vec4i A, Vec4i B)
{
Point P11 = Point(A[0], A[1]);
Point P12 = Point(A[2], A[3]);
Point P21 = Point(B[0], B[1]);
Point P22 = Point(B[2], B[3]);
float ax = P11.x - P12.x;
float ay = P11.y - P12.y;
float bx = P21.x - P22.x;
float by = P21.y - P22.y;
float x = sqrt(ax * ax + ay * ay);
float y = sqrt(bx * bx + by * by);
float ang = (180.0 * acos((ax * bx + ay * by) / (x * y))) / CV_PI;
if (B[2] < B[0]) ang = 360 - ang;
return 360 - ang;
}
int main()
{
Mat image = Mat::zeros(800, 800, CV_8UC3);
Point a = Point(image.cols / 2, image.rows / 2 + 300);
Point b = Point(image.cols / 2, image.rows / 2);
circle(image, b, 5, Scalar(0, 0, 255), -1);
vector<Vec4i> lines = DrawArc(b, a);
RNG& rng = theRNG();
for (int i = 0; i < lines.size(); i++) {
Scalar color = Scalar(rng.uniform(100, 255), rng.uniform(100, 255), rng.uniform(100, 255));
if (i == 0)line(image, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3] + 50), Scalar(0, 0, 255), 2);
else if (i == (lines.size() - 1))line(image, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3] + 50), Scalar(0, 255, 0), 1);
else line(image, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), color, 1);
printf("ANG:%d\t%f\r\n", i, VectorLine(lines[0], lines[i]));
imshow("image", image);
waitKey(30);
}
waitKey(0);
return 0;
}
C#版本如下:
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Point = OpenCvSharp.Point;
using Size = OpenCvSharp.Size;
namespace WindowsFormsApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
List<Vec4i> DrawArc(Point Center, Point Start)
{
List<Vec4i> lines = new List<Vec4i>();
List<Point> Dots = new List<Point>();
double brim = Math.Floor((double)(360 / 1));
Dots.Add(Start);
for (int i = 0; i < brim - 1; i++)
{
double dSinRot = Math.Sin(-(1 * (i + 1)) * Math.PI / 180);
double dCosRot = Math.Cos(-(1 * (i + 1)) * Math.PI / 180);
double x = Center.X + dCosRot * (double)(Start.X - Center.X) - dSinRot * (double)(Start.Y - Center.Y);
double y = Center.Y + dSinRot * (double)(Start.X - Center.X) + dCosRot * (double)(Start.Y - Center.Y);
Dots.Add(new Point((int)x, (int)y));
}
for (int i = 0; i < Dots.Count(); i++)
{
lines.Add(new Vec4i(Center.X, Center.Y, Dots[i].X, Dots[i].Y));
}
Dots.Clear();
return lines;
}
// 计算顺时针角度:0~360
double VectorLine(Vec4i A, Vec4i B)
{
Point P11 = new Point(A[0], A[1]);
Point P12 = new Point(A[2], A[3]);
Point P21 = new Point(B[0], B[1]);
Point P22 = new Point(B[2], B[3]);
double ax = P11.X - P12.X;
double ay = P11.Y - P12.Y;
double bx = P21.X - P22.X;
double by = P21.Y - P22.Y;
double x = Math.Sqrt(ax * ax + ay * ay);
double y = Math.Sqrt(bx * bx + by * by);
double ang = 180.0 * Math.Acos((ax * bx + ay * by) / (x * y)) / Math.PI;
if (B[2] < B[0]) ang = 360 - ang;
return 360 - ang;
}
private void button1_Click(object sender, EventArgs e)
{
Mat image = new Mat(new Size(800, 800), MatType.CV_8UC3, new Scalar(0, 0, 0));
Point a = new Point(image.Width / 2, image.Height / 2 + 300);
Point b = new Point(image.Width / 2, image.Height / 2);
Cv2.Circle(image, b, 5, new Scalar(0, 0, 255), -1);
List<Vec4i> lines = DrawArc(b, a);
RNG rng = new RNG(12345);
for (int i = 0; i < lines.Count(); i++)
{
Scalar color = new Scalar(rng.Uniform(100, 255), rng.Uniform(100, 255), rng.Uniform(100, 255));
if (i == 0)
Cv2.Line(image, new Point(lines[i][0], lines[i][1]), new Point(lines[i][2], lines[i][3] + 50), new Scalar(0, 0, 255), 2);
else if (i == (lines.Count() - 1))
Cv2.Line(image, new Point(lines[i][0], lines[i][1]), new Point(lines[i][2], lines[i][3] + 50), new Scalar(0, 255, 0), 1);
else
Cv2.Line(image, new Point(lines[i][0], lines[i][1]), new Point(lines[i][2], lines[i][3]), color, 1);
System.Diagnostics.Debug.WriteLine($"ANG:{i}\t{VectorLine(lines[0], lines[i])}");
Cv2.ImShow("image", image);
Cv2.WaitKey(1);
}
}
}
}