panlei
2019-07-12 2a7709d4ed9161f145631e2e49ffbde2ce44463f
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
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*100)
    }
    return (perInterPg*100)
}