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) }