panlei
2019-11-01 e6982607fbbeaa96d3d14409df780266646b793d
ruleserver/geoPolygon.go
New file
@@ -0,0 +1,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)
}