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