package service
|
|
import (
|
"basic.com/pubsub/protomsg.git"
|
"basic.com/valib/bhomeclient.git"
|
"basic.com/valib/bhomedbapi.git"
|
"basic.com/valib/logger.git"
|
"encoding/json"
|
"github.com/satori/go.uuid"
|
"vamicro/sync-service/models"
|
"vamicro/sync-service/vo"
|
)
|
|
type CameraPolygonService struct {
|
bk bhomeclient.Broker
|
}
|
|
func NewCameraPolygonService(broker bhomeclient.Broker) *CameraPolygonService {
|
return &CameraPolygonService{
|
bk:broker,
|
}
|
}
|
|
func (sv CameraPolygonService) Save(cPolygon vo.CameraPolygonVo) ([]string,[]string) {
|
var model models.CameraPolygon
|
var delS []string
|
var delF []string
|
|
setPolygons,_ := model.FindAllByCameraId(cPolygon.CameraId)//已经配置的多边形,判断删除的是否有正在使用
|
logger.Debug("setPolygons:",setPolygons)
|
if setPolygons !=nil {
|
delS, delF = sv.getDeletedPolygons(setPolygons, cPolygon)
|
}
|
doResult := false
|
for _,line := range cPolygon.Line {
|
if line.Name != models.CAMERAPOLYGON_AREA_ALL {
|
model.Id = line.Id
|
model.Name = line.Name
|
model.CameraId = cPolygon.CameraId
|
lineBytes, err := json.Marshal(line.Location)
|
if err !=nil {
|
continue
|
}
|
model.Polygon = string(lineBytes)
|
model.Type = models.TYPE_LINE
|
if sv.savePolygon(model) {
|
if !doResult {
|
doResult = true
|
}
|
}
|
}
|
}
|
for _,rect := range cPolygon.Rect {
|
if rect.Name != models.CAMERAPOLYGON_AREA_ALL {
|
rectBytes,_ :=json.Marshal(rect.Location)
|
model = models.CameraPolygon{
|
Id:rect.Id,
|
Name:rect.Name,
|
Polygon:string(rectBytes),
|
CameraId:cPolygon.CameraId,
|
}
|
//判断矩形内是否有箭头
|
arrows := getArrowInPolygon(cPolygon.Arrow, rect.Location)//多边形内部的箭头
|
if len(arrows) >0 {
|
arrowBytes, _ := json.Marshal(arrows[0])//取第一个箭头
|
model.DirectionLine = string(arrowBytes)
|
}
|
model.Type = models.TYPE_RECT
|
if sv.savePolygon(model){
|
if !doResult {
|
doResult = true
|
}
|
}
|
}
|
}
|
for _,pg :=range cPolygon.Polygon{
|
if pg.Name != models.CAMERAPOLYGON_AREA_ALL {
|
pgbytes,_ := json.Marshal(pg.Location)
|
model = models.CameraPolygon{
|
Id:pg.Id,
|
Name:pg.Name,
|
Polygon:string(pgbytes),
|
CameraId:cPolygon.CameraId,
|
}
|
arrows := getArrowInPolygon(cPolygon.Arrow, pg.Location)//多边形内部的箭头
|
if len(arrows) >0 {
|
arrowBytes, _ := json.Marshal(arrows[0])//多边形内只能有一个箭头
|
model.DirectionLine = string(arrowBytes)
|
}
|
model.Type = models.TYPE_POLYGON
|
if sv.savePolygon(model) {
|
if !doResult {
|
doResult = true
|
}
|
}
|
}
|
}
|
sv.addDbChangeMsg(protomsg.DbAction_Update)
|
|
return delS,delF
|
}
|
|
func (sv CameraPolygonService) savePolygon(model models.CameraPolygon) bool {
|
_, flag := model.SelectById(model.Id)
|
|
if flag { //存在则更新
|
existModel,exist := model.Exist(model.CameraId, model.Name)
|
if !exist || (exist && existModel.Id == model.Id) {
|
model.DefenceState = existModel.DefenceState
|
if updateResult,_ :=model.Update();updateResult {
|
sv.addDbChangeMsg(protomsg.DbAction_Update)
|
return true
|
}
|
}
|
} else { //新增
|
_,exist := model.Exist(model.CameraId,model.Name)
|
if exist {
|
return false
|
}
|
model.Id = uuid.NewV4().String()
|
model.DefenceState = 1//新增时区域的布撤防状态默认开启
|
if saveResult,_ :=model.Insert();saveResult{
|
sv.addDbChangeMsg(protomsg.DbAction_Insert)
|
return true
|
}
|
}
|
return false
|
}
|
|
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
|
}
|
|
//取出多边形内部的箭头
|
func getArrowInPolygon(arrows []vo.PolygonS,polygon []vo.Point) (arr []vo.PolygonS){
|
for _,line := range arrows {
|
arrow := line.Location
|
lenth := len(arrow)
|
m :=0
|
for _,point :=range arrow {
|
if pintIsInPolygon(point,polygon){
|
m++
|
} else {
|
break
|
}
|
}
|
if m == lenth{
|
arr = append(arr,line)
|
}
|
}
|
|
return arr
|
}
|
|
//PintIsInPolygon 判断点是否在多边形内部
|
//point为要判断的坐标点
|
//polygon是多边形各点数组
|
func pintIsInPolygon(point vo.Point, polygon []vo.Point) bool {
|
var nCross int = 0
|
for i := 0; i < len(polygon); i++ {
|
p1 := polygon[i]
|
p2 := polygon[(i+1)%len(polygon)]
|
if p1.Y == p2.Y {
|
continue
|
}
|
if point.Y < float64(min(p1.Y, p2.Y)) {
|
continue
|
}
|
if point.Y > float64(max(p1.Y, p2.Y)) {
|
continue
|
}
|
X := (point.Y-float64(p1.Y))*float64((p2.X-p1.X))/float64((p2.Y-p1.Y)) + float64(p1.X)
|
|
if X > point.X {
|
nCross++
|
}
|
}
|
return nCross%2 != 0
|
}
|
|
//返回删除成功的多边形名称数组以及删除失败的多边形名称数组
|
func (sv CameraPolygonService) getDeletedPolygons(setPolygons []models.CameraPolygon,savePolygon vo.CameraPolygonVo)(delS []string,delF []string) {
|
idMap :=make(map[string]string,0)
|
if savePolygon.Line !=nil {
|
for _,line :=range savePolygon.Line {
|
idMap[line.Id] = line.Id
|
}
|
}
|
if savePolygon.Rect !=nil {
|
for _,rect :=range savePolygon.Rect {
|
idMap[rect.Id] = rect.Id
|
}
|
}
|
if savePolygon.Polygon !=nil {
|
for _,polygon :=range savePolygon.Polygon {
|
idMap[polygon.Id] = polygon.Id
|
}
|
}
|
|
var polygonId string
|
var polygonName string
|
for _,model := range setPolygons {
|
polygonId = model.Id
|
polygonName = model.Name
|
if _,ok :=idMap[polygonId];!ok {//多边形已被删除
|
if polygonName != models.CAMERAPOLYGON_AREA_ALL{
|
if model.Delete(polygonId, polygonName) {
|
//将删除掉的区域在规则组中的名称替换为空NULL
|
delS = append(delS,polygonName)//删除成功
|
} else {
|
delF = append(delF,polygonName)//删除失败
|
}
|
}
|
}
|
}
|
if len(delS) >0 {
|
sv.addDbChangeMsg(protomsg.DbAction_Delete)
|
}
|
return delS,delF
|
}
|
|
func (sv CameraPolygonService) FindByCameraId(cameraId string)(vo.CameraPolygonVo){
|
var voInfo = vo.CameraPolygonVo{
|
CameraId:cameraId,
|
}
|
|
if models.IsStack(cameraId) {
|
var sckApi bhomedbapi.FileStackApi
|
b,sck := sckApi.Show(cameraId)
|
if b {
|
voInfo.SnapshotUrl = ""
|
voInfo.CameraName = sck.Name
|
}
|
} else {
|
var cameraE models.Camera
|
rows, e := cameraE.SelectById(cameraId)
|
if e ==nil && rows >0 {
|
voInfo.SnapshotUrl = cameraE.SnapshotUrl
|
voInfo.CameraName = cameraE.Name
|
}
|
}
|
var cameraE models.Camera
|
rows, err := cameraE.SelectById(cameraId)
|
if rows >0 && err ==nil {
|
voInfo.SnapshotUrl = cameraE.SnapshotUrl
|
}
|
|
var cPolygon models.CameraPolygon
|
polygons, _ := cPolygon.FindAllByCameraId(cameraId)
|
|
lines := make([]vo.PolygonS, 0)
|
rects := make([]vo.PolygonS, 0)
|
pgs := make([]vo.PolygonS, 0)
|
//每个摄像机都有个默认的区域,叫全部区域
|
pgs = append(pgs ,vo.PolygonS{
|
Id: cameraId,
|
Name: models.CAMERAPOLYGON_AREA_ALL,
|
Location: []vo.Point{},
|
DefenceState: 1,
|
})
|
directionLines := make([]vo.PolygonS, 0)
|
if polygons !=nil {
|
for _, p := range polygons {
|
location := make([]vo.Point, 0)
|
var dline vo.PolygonS
|
if p.DirectionLine != "" {
|
if err := json.Unmarshal([]byte(p.DirectionLine), &dline); err == nil {
|
//存在一个箭头在多个面内的情况
|
existLine := false
|
for _,el := range directionLines {
|
if el.Id == dline.Id {
|
existLine = true
|
break
|
}
|
}
|
if !existLine {
|
directionLines = append(directionLines, dline)
|
}
|
}
|
}
|
if p.Polygon !=""{
|
if err := json.Unmarshal([]byte(p.Polygon), &location); err == nil {
|
if p.Type == models.TYPE_LINE { //线
|
lines = append(lines, vo.PolygonS{
|
Id: p.Id,
|
Name: p.Name,
|
Location: location,
|
DefenceState: p.DefenceState,
|
})
|
}
|
if p.Type == models.TYPE_RECT {
|
rects = append(rects, vo.PolygonS{
|
Id: p.Id,
|
Name: p.Name,
|
Location: location,
|
DefenceState: p.DefenceState,
|
})
|
}
|
if p.Type == models.TYPE_POLYGON {
|
pgs = append(pgs, vo.PolygonS{
|
Id: p.Id,
|
Name: p.Name,
|
Location: location,
|
DefenceState: p.DefenceState,
|
})
|
}
|
}
|
}
|
}
|
}
|
|
voInfo.Arrow = directionLines
|
voInfo.Line = lines
|
voInfo.Rect = rects
|
voInfo.Polygon = pgs
|
|
return voInfo
|
}
|
|
func (sv CameraPolygonService)addDbChangeMsg(action protomsg.DbAction){
|
dbMsg := protomsg.DbChangeMessage{
|
Table:protomsg.TableChanged_T_CameraPolygon,
|
Action:action,
|
}
|
pb,_ := json.Marshal(dbMsg)
|
sv.bk.Publish(ProcName, pb)
|
}
|