panlei
2019-11-06 2cbca7d108329ec8b48a69f7cb7528e58885607c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package ruleserver
 
import (
    "math"
    "ruleprocess/structure"
)
 
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 structure.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 structure.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*100)
    }
    return (perInterPg*100)
}