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"
|
"strings"
|
"vamicro/scene-service/models"
|
"vamicro/scene-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 = getDeletedPolygons(setPolygons, cPolygon)
|
}
|
doResult := false
|
var chIdArr []string
|
for _, line := range cPolygon.Line {
|
if line.Name != models.CAMERAPOLYGON_AREA_ALL {
|
chIdArr = append(chIdArr, line.Id)
|
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 savePolygon(model) {
|
if !doResult {
|
doResult = true
|
}
|
}
|
}
|
}
|
for _, rect := range cPolygon.Rect {
|
if rect.Name != models.CAMERAPOLYGON_AREA_ALL {
|
chIdArr = append(chIdArr, rect.Id)
|
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 savePolygon(model) {
|
if !doResult {
|
doResult = true
|
}
|
}
|
}
|
}
|
for _, pg := range cPolygon.Polygon {
|
if pg.Name != models.CAMERAPOLYGON_AREA_ALL {
|
chIdArr = append(chIdArr, pg.Id)
|
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 savePolygon(model) {
|
if !doResult {
|
doResult = true
|
}
|
}
|
}
|
}
|
sv.addDbChangeMsg(chIdArr, protomsg.DbAction_Update)
|
|
return delS, delF
|
}
|
|
func 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 {
|
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 {
|
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 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, savePolygon.Force) {
|
//将删除掉的区域在规则组中的名称替换为空NULL
|
delS = append(delS, polygonName) //删除成功
|
} else {
|
delF = append(delF, polygonName) //删除失败
|
}
|
}
|
}
|
}
|
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, fileS := sckApi.Show(cameraId)
|
if b {
|
voInfo.SnapshotUrl = ""
|
voInfo.CameraName = fileS.Name
|
}
|
} else {
|
//可能是本地摄像机
|
var localCamApi bhomedbapi.CameraApi
|
localCam, err := localCamApi.GetCameraById(cameraId)
|
if err == nil && localCam.SnapshotUrl != "" {
|
voInfo.SnapshotUrl = localCam.SnapshotUrl
|
voInfo.CameraName = localCam.Name
|
} else {
|
//也可能是国标摄像机
|
var gbCamApi bhomedbapi.Gb28181Api
|
gbCamera, err := gbCamApi.GetCameraById(cameraId)
|
if err == nil && gbCamera.SnapshotUrl != "" {
|
voInfo.SnapshotUrl = gbCamera.SnapshotUrl
|
voInfo.CameraName = localCam.Name
|
}
|
}
|
}
|
|
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(chIdArr []string, action protomsg.DbAction) {
|
dbMsg := protomsg.DbChangeMessage{
|
Table: protomsg.TableChanged_T_CameraPolygon,
|
Id: strings.Join(chIdArr, ","),
|
Action: action,
|
Info: string(""),
|
}
|
bts, _ := json.Marshal(&dbMsg)
|
sv.bk.Publish(ProcName, bts)
|
}
|
|
func (sv CameraPolygonService) addPgnRelationMsg(action protomsg.DbAction) {
|
dbMsg := protomsg.DbChangeMessage{
|
Table: protomsg.TableChanged_T_CameraPolygonRelation,
|
Id: "",
|
Action: action,
|
Info: string(""),
|
}
|
bts, _ := json.Marshal(&dbMsg)
|
sv.bk.Publish(ProcName, bts)
|
}
|
|
// 获取同步摄像机场景的数据
|
func (sv CameraPolygonService) GetSyncSceneData() vo.SyncPolygonResult {
|
res := vo.SyncPolygonResult{}
|
cameraGroupM := models.CameraGroup{}
|
cameraPolyginM := models.CameraPolygon{}
|
cameraPolygonRelationM := models.CameraPolygonRelation{}
|
cameraRuleGroupM := models.CameraRuleGroup{}
|
cameraRuleGroupArgM := models.CameraRuleGroupArg{}
|
cameraTaskLinkM := models.CameraTaskLink{}
|
cameraTimeruleM := models.CameraTimerule{}
|
|
res.CameraPolygon = cameraPolyginM.FindAll()
|
res.CameraGroup = cameraGroupM.FindAll()
|
res.CameraPolygonRelation = cameraPolygonRelationM.FindAll()
|
res.CameraRuleGroup = cameraRuleGroupM.FindAll()
|
res.CameraRuleGroupArg = cameraRuleGroupArgM.FindAll()
|
res.CameraTaskLink, _ = cameraTaskLinkM.FindAll()
|
res.CameraTimerule, _ = cameraTimeruleM.FindAll()
|
|
return res
|
}
|
|
func (sv CameraPolygonService) DeleteByIds(ids []string) bool {
|
var cp models.CameraPolygon
|
if !cp.DeleteByIds(ids) {
|
return false
|
}
|
|
sv.addDbChangeMsg(ids, protomsg.DbAction_Delete)
|
return true
|
}
|