package ruleserver
|
|
import (
|
"math"
|
)
|
|
func min(num1 float64, num2 float64) float64 {
|
if num1 < num2 {
|
return num1
|
}
|
return num2
|
|
}
|
|
func max(num1 float64, num2 float64) float64 {
|
if num1 < num2 {
|
return num2
|
}
|
return num1
|
}
|
|
//Point 坐标点
|
type Point struct {
|
X float64 `json:"x"`
|
Y float64 `json:"y"`
|
}
|
|
//Rect 检测目标
|
type Rect struct {
|
X float64
|
Y float64
|
Width float64
|
Height float64
|
}
|
|
//Pointfloat 坐标点
|
type Pointfloat struct {
|
X float64 `json:"x"`
|
Y float64 `json:"y"`
|
}
|
|
//PintIsInPolygon 判断点是否在多边形内部
|
//point为要判断的坐标点
|
//polygon是多边形各点数组
|
func pintIsInPolygon(point Pointfloat, polygon []Point, widthScale float64, heightScale float64) bool {
|
var nCross int = 0
|
for i := 0; i < len(polygon); i++ {
|
|
p1 := polygon[i]
|
p2 := polygon[(i+1)%len(polygon)]
|
// 根据摄像机所拍图像与前端画布的比例将区域放大
|
p1.X = p1.X * widthScale
|
p1.Y = p1.Y * heightScale
|
p2.X = p2.X * widthScale
|
p2.Y = p2.Y * heightScale
|
if p1.Y == p2.Y {
|
continue
|
}
|
if point.Y < min(p1.Y, p2.Y) {
|
continue
|
}
|
if point.Y > max(p1.Y, p2.Y) {
|
continue
|
}
|
X := (point.Y-p1.Y)*(p2.X-p1.X)/(p2.Y-p1.Y) + p1.X
|
|
if X > point.X {
|
nCross++
|
}
|
}
|
return nCross%2 != 0
|
}
|
|
//GetLocation 将一个给定起始坐标,宽度长度的矩形区域均分为n方份并返回中心坐标(n为单边平分数值)和面积
|
func getLocation(rect Rect, n int) ([]Pointfloat, float64) {
|
xArr := make([]float64, n) // 用切片不用数组,数组不能用变量定义长度
|
yArr := make([]float64, n)
|
pointArr := make([]Pointfloat, 0, n*n)
|
for i := 0; i < n; i++ {
|
xArr[i] = rect.X + (rect.Width/float64(2*n))*float64(2*i+1)
|
yArr[i] = rect.Y + (rect.Height/float64(2*n))*float64(2*i+1)
|
}
|
for i := 0; i < n; i++ {
|
for j := 0; j < n; j++ {
|
point := Pointfloat{X: xArr[i], Y: yArr[j]}
|
pointArr = append(pointArr, point)
|
}
|
}
|
s := rect.Width * rect.Height
|
return pointArr, s
|
}
|
|
//ComputePolygonArea 计算任意多边形面积
|
func computePolygonArea(polygon []Point) float64 {
|
pointNum := len(polygon)
|
var s float64 = 0
|
if pointNum < 3 {
|
s = 0
|
}
|
for i := 0; i < pointNum; i++ {
|
s += polygon[i].X*polygon[(i+1)%pointNum].Y - polygon[i].Y*polygon[(i+1)%pointNum].X
|
}
|
area := math.Abs(s / 2)
|
return area
|
}
|
|
//PgsInterPercent calculate percent of two polygon intersection 计算两个多边形的重叠占比
|
func PgsInterPercent(pgpts []Point, box Rect, widthScale float64, heightScale float64) (percent float64) {
|
|
areapts, areaBox := getLocation(box, 10)
|
var count = 0
|
for _, pts := range areapts {
|
if pintIsInPolygon(pts, pgpts, widthScale, heightScale) {
|
count++
|
}
|
}
|
perInterBox := float64(count) / float64(len(areapts)) // 重合面积占矩形的比例
|
areaInter := perInterBox * areaBox
|
areaPg := computePolygonArea(pgpts)
|
perInterPg := areaInter / areaPg // 重合面积占多边形区域的比例
|
// 哪个占的比例大按哪个计算
|
if perInterBox > perInterPg {
|
return perInterBox
|
}
|
return perInterPg
|
}
|