diff --git a/src/app/system-management/host-config/host-config.component.ts b/src/app/system-management/host-config/host-config.component.ts
index b21ad4b..c17f0f5 100644
--- a/src/app/system-management/host-config/host-config.component.ts
+++ b/src/app/system-management/host-config/host-config.component.ts
@@ -20,6 +20,7 @@ import { catchError, tap } from 'rxjs/operators';
import { ConfigFormDataService } from 'src/app/service/configFormData.service';
import { SendFileComponent } from './send-file/send-file.component';
import { ImageLabel2Component } from '../image-label2/image-label2.component';
+import { ImageLabelComponent } from '../image-label/image-label.component';
interface Camera {
name: string;
user: string;
@@ -50,9 +51,12 @@ export class HostConfigComponent implements OnInit {
hostId; //主机id
orId; //加油站id
+ hostType; //黄海还是交大的盒子
ngOnInit(): void {
this.hostId = this.route.snapshot.queryParams.hostId;
this.orId = this.route.snapshot.queryParams.orId;
+
+ this.hostType = this.route.snapshot.queryParams.type;
this.getCamera();
this.http.get(`/api/EdgeDevices/${this.hostId}`).subscribe({
@@ -203,15 +207,46 @@ export class HostConfigComponent implements OnInit {
label(item) {
this.http.get(`/api/EdgeDevices/${this.hostId}`).subscribe({
next: (data: any) => {
- if (data.configFiles) {
- this.isSourceYaml = true;
+ if (this.hostType == '交大') {
+ if (data.configFiles) {
+ this.isSourceYaml = true;
+ const element = document.documentElement;
+ if (element.requestFullscreen) {
+ //进入全屏
+ element.requestFullscreen();
+ }
+ const modal = this.modal.create({
+ nzContent: ImageLabel2Component,
+ nzViewContainerRef: this.viewContainerRef,
+ nzWidth: 1920,
+ nzClosable: false,
+ nzFooter: null,
+ nzWrapClassName: 'canvasContentBox',
+ nzBodyStyle: {
+ 'border-radius': '0px',
+ padding: '0px',
+ margin: '0px',
+ },
+ nzComponentParams: {
+ data: item.id,
+ },
+ nzOnOk: async () => {},
+ });
+ modal.afterClose.subscribe((result) => {
+ this.ngOnInit();
+ });
+ } else {
+ this.isSourceYaml = false;
+ this.message.create('error', '请先下发source.yaml配置');
+ }
+ } else if (this.hostType == '黄海') {
const element = document.documentElement;
if (element.requestFullscreen) {
//进入全屏
element.requestFullscreen();
}
const modal = this.modal.create({
- nzContent: ImageLabel2Component,
+ nzContent: ImageLabelComponent,
nzViewContainerRef: this.viewContainerRef,
nzWidth: 1920,
nzClosable: false,
@@ -223,24 +258,15 @@ export class HostConfigComponent implements OnInit {
margin: '0px',
},
nzComponentParams: {
- data: item.id,
+ cameraId: item.id,
},
- nzOnOk: async () => {},
});
- const instance = modal.getContentComponent();
-
modal.afterClose.subscribe((result) => {
this.ngOnInit();
});
- //this.router.navigate(['/system/host/camera/imageLabel'], { queryParams: { id: item.id } })
- } else {
- this.isSourceYaml = false;
- this.message.create('error', '请先下发source.yaml配置');
}
},
- error: (err) => {
- // this.message.create('error', '请先下发source.yaml配置');
- },
+ error: (err) => {},
});
}
@@ -1110,4 +1136,7 @@ rule_threshold:
sessionStorage.setItem('config3', config3);
sessionStorage.setItem('config4', config4);
}
+
+ //黄海配置文件
+ config() {}
}
diff --git a/src/app/system-management/image-label/image-label.component.html b/src/app/system-management/image-label/image-label.component.html
index 9b2c16e..c0293d7 100644
--- a/src/app/system-management/image-label/image-label.component.html
+++ b/src/app/system-management/image-label/image-label.component.html
@@ -1,12 +1,51 @@
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/src/app/system-management/image-label/image-label.component.scss b/src/app/system-management/image-label/image-label.component.scss
index 89f7b5b..8ee26e6 100644
--- a/src/app/system-management/image-label/image-label.component.scss
+++ b/src/app/system-management/image-label/image-label.component.scss
@@ -1,26 +1,77 @@
-.box {
+.canvasBox {
width: 100%;
height: 100%;
+ background: #fff;
+ font-size: 15px;
+ color: black;
+ box-sizing: border-box;
display: flex;
flex-direction: column;
-}
+ overflow: hidden;
-.btnbox {
- margin-bottom: 5px;
- button {
- margin-right: 15px;
+ .imgbox {
+ flex: 1;
+ overflow: hidden;
}
-}
-.selectBtn { background-color: #1890ff; color: #fff; }
-.imgbox {
- width: 100%;
- height:500px;
- overflow: hidden;
- canvas{ overflow: hidden; }
- .content,.center{
+ canvas {
+ overflow: hidden;
+ display: block;
+ }
+
+ .content,
+ .center {
width: 100%;
height: 100%;
overflow: hidden;
}
}
+
+.btnbox {
+ display: flex;
+ position: fixed;
+ left: 1%;
+ top: 1%;
+ z-index: 10;
+
+ button {
+ margin-right: 6px;
+ display: flex;
+ }
+
+ .deleteItem {
+ display: none;
+ color: red;
+ cursor: pointer;
+ margin-left: 5px;
+ }
+
+ button:hover {
+ .deleteItem {
+ display: block;
+ }
+ }
+
+ .leftTitle {
+ line-height: 32px;
+ margin-right: 10px;
+ color: #fff;
+ }
+
+ .rightTitle {
+ line-height: 32px;
+ margin-left: 10px;
+ color: #fff;
+ }
+}
+
+.imgbox,
+.btnbox {
+ box-sizing: border-box;
+ padding: 0;
+}
+
+.selectBtn {
+ background-color: #1890ff;
+ color: #fff;
+}
diff --git a/src/app/system-management/image-label/image-label.component.ts b/src/app/system-management/image-label/image-label.component.ts
index 43cf808..61ffd3a 100644
--- a/src/app/system-management/image-label/image-label.component.ts
+++ b/src/app/system-management/image-label/image-label.component.ts
@@ -1,216 +1,762 @@
-import { Component, OnInit } from '@angular/core';
+import { HttpClient, HttpErrorResponse } from '@angular/common/http';
+import { Component, Input, OnInit } from '@angular/core';
+import { NzMessageService } from 'ng-zorro-antd/message';
+import { NzModalService } from 'ng-zorro-antd/modal';
@Component({
selector: 'app-image-label',
templateUrl: './image-label.component.html',
- styleUrls: ['./image-label.component.scss']
+ styleUrls: ['./image-label.component.scss'],
})
export class ImageLabelComponent implements OnInit {
+ constructor(
+ private http: HttpClient,
+ private message: NzMessageService,
+ private modal: NzModalService
+ ) {}
- constructor() { }
-
- imgItem: any;
+ @Input() cameraId: any; //传递id
+ camerasData: any; //摄像头Data
+ imgItem: any; //图片 URL
canvasWidth: number = 0;
canvasHeight: number = 0;
- copyCanvas: any;
- markType: boolean = true; //标注type
+ copyCanvas: any; //拷贝 canvas底图
+
+ selectedBtn: string; //按钮选中
+ //返回上一步路由
+ goback() {
+ history.go(-1);
+ }
+
+ ngOnInit(): void {}
+
+ //获取 摄像头图片/标注点位
+ getImgMarkData() {
+ return new Promise((resolve, reject) => {
+ this.http.get(`/api/Cameras/${this.cameraId}`).subscribe((info: any) => {
+ info.dimensionedPoints
+ ? (info.dimensionedPoints = JSON.parse(info.dimensionedPoints))
+ : null;
+ this.camerasData = info;
+ this.markType = info.type;
- ngOnInit(): void {
+ this.markType === 3
+ ? (this.selectedBtn = '收银区')
+ : (this.selectedBtn = '停车区');
+ const httpOptions = {
+ responseType: 'blob' as 'json',
+ params: { cameraId: this.cameraId },
+ };
+ this.http.get(`/api/Cameras/Images`, httpOptions).subscribe({
+ next: (data) => {
+ resolve(data);
+ },
+ error: (err) => {
+ reject('error');
+ },
+ });
+ });
+ });
+ }
+ anewgetImg() {
+ let params = {
+ cameraId: this.cameraId,
+ };
+ this.http
+ .put('/api/Cameras/Commands/CaptureImages', '', { params: params })
+ .subscribe({
+ next: (value: Object) => {
+ this.message.create(
+ 'success',
+ '向边缘设备发送请求成功,请过一段时间手动刷新页面!'
+ );
+ },
+ error: (error: HttpErrorResponse) => {},
+ complete: () => {},
+ });
}
ngAfterContentInit(): void {
- this.initBackgroundImg()
+ this.getImgMarkData()
+ .then((res: any) => {
+ this.imgItem = window.URL.createObjectURL(res);
+ window.setTimeout(() => {
+ this.initBackgroundImg();
+ }, 0);
+ })
+ .catch((err) => {
+ this.message.create('error', '获取图片失败!');
+ });
}
//初始化背景图
+
+ canvas;
+ ctx;
+
initBackgroundImg() {
- let canvas = document.getElementById('canvas') as any;
- canvas.oncontextmenu = () =>{ return false; };
- let that = this
- let ctx
+ this.canvas = document.getElementById('canvas') as any;
+ //取消鼠标右键事件
+ this.canvas.oncontextmenu = () => {
+ return false;
+ };
// 检测canvas支持性
- if (canvas.getContext) {
- ctx = canvas.getContext('2d'); // 返回一个对象,该对象提供了用在画布上绘图的方法和属性
+ if (this.canvas.getContext) {
+ this.ctx = this.canvas.getContext('2d'); // 返回一个对象,该对象提供了用在画布上绘图的方法和属性
} else {
- document.write("你的浏览器不支持canvas,请升级你的浏览器!");
+ document.write('你的浏览器不支持canvas,请升级你的浏览器!');
return;
}
-
- // 读取可视区域 宽高
- let center = (document.getElementById('canvasCenter') as any).getBoundingClientRect();
-
// 图片加载完后,将其显示在canvas中
var img = new Image();
- img.src = that.imgItem.url? that.imgItem.url : "../../../assets/images/bgImg.png";
+ img.src = this.imgItem ? this.imgItem : '../../../assets/images/bgImg.png';
img.onload = () => {
- // 等比例缩放图片
- var scale = 1;
- if (img.width > center.width || img.height > center.height) {
- if (img.width > img.height) {
- scale = center.width / img.width;
- }else {
- scale = center.height / img.height;
+ this.canvasWidth = img.width;
+ this.canvasHeight = img.height;
+ window.setTimeout(() => {
+ // 加载图片
+ this.ctx.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight);
+ this.copyCanvas = this.ctx.getImageData(
+ 0,
+ 0,
+ this.canvasWidth,
+ this.canvasHeight
+ );
+ //初始化标绘图形
+ this.initMark(this.canvas, this.ctx);
+ //监听canvas事件
+ this.initCanvasEvent(this.canvas);
+ }, 0);
+ };
+ }
+
+ //初始化标绘图形
+ initMark(canvas, context) {
+ this.camerasData.dimensionedPointsOfHH = sessionStorage.getItem('xxx');
+
+ if (!this.camerasData.dimensionedPointsOfHH) {
+ return;
+ } else {
+ this.camerasData.dimensionedPointsOfHH = JSON.parse(
+ this.camerasData.dimensionedPointsOfHH
+ );
+ }
+
+ console.log('原始标点数据', this.camerasData.dimensionedPointsOfHH);
+
+ return;
+ //绘制停车区多边形
+ this.camerasData.dimensionedPointsOfHH.carStopROI.forEach((element) => {
+ this.carStopROIDrawPolygon(element.x, element.y, canvas, context);
+ });
+
+ //绘制收银区多边形
+ this.camerasData.dimensionedPointsOfHH.cashierROI.forEach((element) => {
+ this.cashierROIDrawPolygon(element.x, element.y, canvas, context);
+ });
+
+ //绘制闯入区多边形
+ this.camerasData.dimensionedPointsOfHH.intrusionROI.forEach((element) => {
+ this.intrusionROIDrawPolygon(element.x, element.y, canvas, context);
+ });
+
+ //绘制卸油区矩形
+ this.unloadingROIDrawOblong(
+ this.camerasData.dimensionedPointsOfHH.unloadingROI,
+ context
+ );
+ }
+
+ markType: number = 0; //0=进出口,1=加油区,2=卸油区,3=便利店,
+
+ //记录鼠标点击位置
+ downx = 0;
+ downy = 0;
+
+ //初始化 canvas画布 监听事件
+ context;
+ initCanvasEvent(canvas) {
+ var context = canvas.getContext('2d');
+ this.context = context;
+ canvas.onmousedown = (e) => {
+ //鼠标按下事件
+ var clickX = e.pageX - canvas.offsetLeft;
+ var clickY = e.pageY - canvas.offsetTop;
+ this.downx = clickX;
+ this.downy = clickY;
+
+ if (this.markType === 0) {
+ //进出口
+ this.carStopROIDrawPolygon(clickX, clickY, canvas, context); //绘制停车区
+ } else if (this.markType === 1) {
+ //加油区(暂不需要标注)
+ } else if (this.markType === 2) {
+ //卸油区
+ if (this.selectedBtn === '停车区') {
+ this.carStopROIDrawPolygon(clickX, clickY, canvas, context); //绘制停车区
+ } else if (this.selectedBtn === '闯入区') {
+ this.intrusionROIDrawPolygon(clickX, clickY, canvas, context); //绘制闯入区
+ } else if (this.selectedBtn === '卸油区') {
+ if (this.unloadingROIOblongPoints.length === 1) {
+ //限制数量
+ this.message.create('warning', '卸油区只允许绘制1个!');
+ return;
+ }
+
+ //绘制矩形
+ context.beginPath();
+ context.moveTo(clickX, clickY);
+ context.strokeStyle = 'green';
+ context.lineWidth = 3;
+ canvas.onmousemove = (ev) => {
+ //鼠标移动事件
+ var moveX = ev.pageX - canvas.offsetLeft;
+ var moveY = ev.pageY - canvas.offsetTop;
+
+ this.unloadingROIDrawOblong(this.unloadingROIOblongPoints, context);
+ context.strokeStyle = 'orange';
+ let element = this.getOblongInfo(
+ this.downx,
+ this.downy,
+ moveX,
+ moveY
+ );
+ context.strokeRect(
+ element.x,
+ element.y,
+ element.width,
+ element.height
+ );
+ context.font = '22px Arial';
+ context.fillText(
+ '高度:' + element.height,
+ element.x + 3,
+ element.y + 22
+ );
+ };
}
+ //
+ } else if (this.markType === 3) {
+ //便利店
+ this.cashierROIDrawPolygon(clickX, clickY, canvas, context); //绘制停车区
}
- that.canvasWidth = img.width * scale;
- that.canvasHeight = img.height * scale; // 计算等比缩小后图片
- window.setTimeout(()=>{ // 加载图片
- ctx.drawImage(img, 0, 0, that.canvasWidth, that.canvasHeight);
- this.copyCanvas = ctx.getImageData(0, 0, that.canvasWidth, that.canvasHeight)
- that.initCanvasEvent(canvas)
- }, 0)
- }
- }
-
- //线段的点的集合
- points = [];
- points2 = [];
- //可拖动圆圈的点的集合
- circles = [];
- circles2 = [];
- //整体移动点位
- allpoints = [];
- allpoints2 = [];
- isDragging = false
- //是否在绘制区域内
- isInOut = false
- //记录鼠标点击位置
- downx = 0
- downy = 0
+ };
+
+ canvas.onmouseup = (e) => {
+ //鼠标松开事件
+ canvas.onmousemove = (ev) => {
+ //鼠标移动事件
+ return false;
+ };
+ if (this.markType !== 2) {
+ //因为只有卸油区需要画矩形
+ return;
+ }
+ if (this.markType === 2 && this.unloadingROIOblongPoints.length === 1) {
+ return;
+ }
+ if (this.markType === 2 && this.selectedBtn === '卸油区') {
+ var upX = e.pageX - canvas.offsetLeft;
+ var upY = e.pageY - canvas.offsetTop;
+ let point = this.getOblongInfo(this.downx, this.downy, upX, upY);
+ this.unloadingROIOblongPoints.push(point);
+ this.unloadingROIDrawOblong(this.unloadingROIOblongPoints, context);
+ }
+ };
+ }
+
+ //卸油区矩形
+ unloadingROIOblongPoints = []; //矩形的点的集合
+ unloadingROIDrawOblong(oblongList, context) {
+ context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null;
+
+ //重绘停车区
+ if (this.carStopROIPoints && this.carStopROIPoints.length != 0) {
+ this.redrawPolygon(
+ this.carStopROIPoints,
+ this.carStopROIAllpoints,
+ this.carStopROICircles,
+ context,
+ 'green'
+ );
+ }
+
+ //重绘闯入区
+ if (this.carStopROIPoints && this.carStopROIPoints.length != 0) {
+ this.redrawPolygon(
+ this.intrusionROIPoints,
+ this.intrusionROIAllpoints,
+ this.intrusionROICircles,
+ context,
+ 'red'
+ );
+ }
+ oblongList.forEach((element) => {
+ context.strokeStyle = 'orange';
+ context.lineWidth = 3;
+ context.strokeRect(element.x, element.y, element.width, element.height);
+ context.font = '22px Arial';
+ context.fontColor = 'orange';
+ context.fillText('高度:' + element.height, element.x + 3, element.y + 22);
+ });
+ }
+ /** 获取 矩形左上角点位/宽高 */
+ getOblongInfo(startX, startY, endX, endY) {
+ let point = {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ };
+ if (startX > endX) {
+ point.x = endX;
+ point.width = startX - endX;
+ } else {
+ point.x = startX;
+ point.width = endX - startX;
+ }
+ if (startY > endY) {
+ point.y = endY;
+ point.height = startY - endY;
+ } else {
+ point.y = startY;
+ point.height = endY - startY;
+ }
+ return point;
+ }
+
+ //停车区多边形
+ carStopROIPoints = []; //线段的点的集合
+ carStopROICircles = []; //可拖动圆圈的点的集合
+ carStopROIAllpoints = []; //整体移动点位
+ carStopROIIsDragging = false; //是否可拖拽
+ carStopROIIsInOut = false; //是否在绘制区域内
+ carStopROIDrawPolygon(clickX, clickY, canvas, context) {
+ if (this.isInt(clickX, clickY, this.carStopROIPoints)) {
+ this.carStopROIIsInOut = true;
+ return;
+ } else {
+ this.carStopROIIsInOut = false;
+ }
+ let index;
+ //判断当前点击点是否在已经绘制的圆圈上,如果是执行相关操作,并return,不进入画线的代码
+ for (var i = 0; i < this.carStopROICircles.length; i++) {
+ let circle = this.carStopROICircles[i];
+ //使用勾股定理计算这个点与圆心之间的距离
+ var distanceFromCenter = Math.sqrt(
+ Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2)
+ );
+ // 如果是其他的点,则设置可以拖动
+ if (distanceFromCenter <= circle.radius) {
+ // 清除之前选择的圆圈
+ index = i;
+ this.carStopROIIsDragging = true;
+ //停止搜索
+ return;
+ }
+ }
+ //如果点击新的位置,则进入下面的代码,绘制点
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null;
+
+ //重绘闯入区
+ if (this.carStopROIPoints && this.carStopROIPoints.length != 0) {
+ this.redrawPolygon(
+ this.intrusionROIPoints,
+ this.intrusionROIAllpoints,
+ this.intrusionROICircles,
+ context,
+ 'red'
+ );
+ }
+
+ //重绘卸油区
+ if (
+ this.unloadingROIOblongPoints &&
+ this.unloadingROIOblongPoints.length != 0
+ ) {
+ this.redrawRectangle(this.unloadingROIOblongPoints, context);
+ }
+
+ //遍历数组画圆
+ var circle = {
+ x: clickX,
+ y: clickY,
+ radius: 5,
+ color: 'white',
+ isSelected: false, //拖拽点的标记
+ };
+ this.carStopROICircles.push(circle);
+ this.carStopROIAllpoints = JSON.parse(
+ JSON.stringify(this.carStopROICircles)
+ );
+ this.carStopROICircles[0].color = 'white';
+ for (var i = 0; i < this.carStopROICircles.length; i++) {
+ let circle = this.carStopROICircles[i];
+ // 绘制圆圈
+ context.globalAlpha = 0.85;
+ context.beginPath();
+ context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
+ context.fillStyle = circle.color;
+ context.strokeStyle = 'red';
+ context.fill();
+ context.stroke();
+ }
+ // 画线
+ var point = {
+ x: clickX,
+ y: clickY,
+ };
+ this.carStopROIPoints.push(point);
+ context.beginPath();
+ context.lineWidth = 3;
+ //从起始点开始绘制
+ context.moveTo(this.carStopROIPoints[0].x, this.carStopROIPoints[0].y);
+ for (var i = 0; i < this.carStopROIPoints.length; i++) {
+ context.lineTo(this.carStopROIPoints[i].x, this.carStopROIPoints[i].y);
+ }
+ context.closePath();
+ context.strokeStyle = 'green';
+ context.stroke();
+ }
+
+ //闯入区多边形
+ intrusionROIPoints = []; //线段的点的集合
+ intrusionROICircles = []; //可拖动圆圈的点的集合
+ intrusionROIAllpoints = []; //整体移动点位
+ intrusionROIIsDragging = false; //是否可拖拽
+ intrusionROIIsInOut = false; //是否在绘制区域内
+ intrusionROIDrawPolygon(clickX, clickY, canvas, context) {
+ if (this.isInt(clickX, clickY, this.intrusionROIPoints)) {
+ this.intrusionROIIsInOut = true;
+ return;
+ } else {
+ this.intrusionROIIsInOut = false;
+ }
+ let index;
+ //判断当前点击点是否在已经绘制的圆圈上,如果是执行相关操作,并return,不进入画线的代码
+ for (var i = 0; i < this.intrusionROICircles.length; i++) {
+ let circle = this.intrusionROICircles[i];
+ //使用勾股定理计算这个点与圆心之间的距离
+ var distanceFromCenter = Math.sqrt(
+ Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2)
+ );
+
+ // 如果是其他的点,则设置可以拖动
+ if (distanceFromCenter <= circle.radius) {
+ // 清除之前选择的圆圈
+ index = i;
+ this.intrusionROIIsDragging = true;
+ //停止搜索
+ return;
+ }
+ }
+
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null;
+
+ //重绘停车区
+ if (this.carStopROIPoints && this.carStopROIPoints.length != 0) {
+ this.redrawPolygon(
+ this.carStopROIPoints,
+ this.carStopROIAllpoints,
+ this.carStopROICircles,
+ context,
+ 'green'
+ );
+ }
+
+ //重绘卸油区
+ if (
+ this.unloadingROIOblongPoints &&
+ this.unloadingROIOblongPoints.length != 0
+ ) {
+ this.redrawRectangle(this.unloadingROIOblongPoints, context);
+ }
+
+ //遍历数组画圆
+ var circle = {
+ x: clickX,
+ y: clickY,
+ radius: 5,
+ color: 'white',
+ isSelected: false, //拖拽点的标记
+ };
+ this.intrusionROICircles.push(circle);
+ this.intrusionROIAllpoints = JSON.parse(
+ JSON.stringify(this.intrusionROICircles)
+ );
+ this.intrusionROICircles[0].color = 'white';
+ for (var i = 0; i < this.intrusionROICircles.length; i++) {
+ let circle = this.intrusionROICircles[i];
+ // 绘制圆圈
+ context.globalAlpha = 0.85;
+ context.beginPath();
+ context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
+ context.fillStyle = circle.color;
+ context.strokeStyle = 'red';
+ context.fill();
+ context.stroke();
+ }
+ // 画线
+ var point = {
+ x: clickX,
+ y: clickY,
+ };
+ this.intrusionROIPoints.push(point);
+ context.beginPath();
+ context.lineWidth = 3;
+ //从起始点开始绘制
+ context.moveTo(this.intrusionROIPoints[0].x, this.intrusionROIPoints[0].y);
+ for (var i = 0; i < this.intrusionROIPoints.length; i++) {
+ context.lineTo(
+ this.intrusionROIPoints[i].x,
+ this.intrusionROIPoints[i].y
+ );
+ }
+ context.closePath();
+ context.strokeStyle = 'red';
+ context.stroke();
+ }
+
+ //收银区多边形
+ cashierROIPoints = []; //线段的点的集合
+ cashierROICircles = []; //可拖动圆圈的点的集合
+ cashierROIAllpoints = []; //整体移动点位
+ cashierROIIsDragging = false; //是否可拖拽
+ cashierROIIsInOut = false; //是否在绘制区域内
+ cashierROIDrawPolygon(clickX, clickY, canvas, context) {
+ if (this.isInt(clickX, clickY, this.cashierROIPoints)) {
+ this.cashierROIIsInOut = true;
+ return;
+ } else {
+ this.cashierROIIsInOut = false;
+ }
+ let index;
+ //判断当前点击点是否在已经绘制的圆圈上,如果是执行相关操作,并return,不进入画线的代码
+ for (var i = 0; i < this.cashierROICircles.length; i++) {
+ let circle = this.cashierROICircles[i];
+ //使用勾股定理计算这个点与圆心之间的距离
+ var distanceFromCenter = Math.sqrt(
+ Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2)
+ );
+
+ // 如果是其他的点,则设置可以拖动
+ if (distanceFromCenter <= circle.radius) {
+ // 清除之前选择的圆圈
+ index = i;
+ this.cashierROIIsDragging = true;
+ //停止搜索
+ return;
+ }
+ }
+
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null;
+
+ //遍历数组画圆
+ var circle = {
+ x: clickX,
+ y: clickY,
+ radius: 5,
+ color: 'yellow',
+ isSelected: false, //拖拽点的标记
+ };
+ this.cashierROICircles.push(circle);
+ this.cashierROIAllpoints = JSON.parse(
+ JSON.stringify(this.cashierROICircles)
+ );
+ this.cashierROICircles[0].color = 'white';
+ for (var i = 0; i < this.cashierROICircles.length; i++) {
+ let circle = this.cashierROICircles[i];
+ // 绘制圆圈
+ context.globalAlpha = 0.85;
+ context.beginPath();
+ context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
+ context.fillStyle = circle.color;
+ context.strokeStyle = 'red';
+ context.fill();
+ context.stroke();
+ }
+ // 画线
+ var point = {
+ x: clickX,
+ y: clickY,
+ };
+ this.cashierROIPoints.push(point);
+ context.beginPath();
+ context.lineWidth = 3;
+ //从起始点开始绘制
+ context.moveTo(this.cashierROIPoints[0].x, this.cashierROIPoints[0].y);
+ for (var i = 0; i < this.cashierROIPoints.length; i++) {
+ context.lineTo(this.cashierROIPoints[i].x, this.cashierROIPoints[i].y);
+ }
+ context.closePath();
+ context.strokeStyle = 'blue';
+ context.stroke();
+ }
+ //判断点位是否在图形区域内
+ isInt(x, y, points) {
+ if (!points[2]) {
+ return;
+ }
+ var pt = {
+ x: x,
+ y: y,
+ };
+ return this.PointInPoly(pt, points);
+ }
+ //射线法判断点位
+ PointInPoly(pt, poly) {
+ for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
+ ((poly[i].y <= pt.y && pt.y < poly[j].y) ||
+ (poly[j].y <= pt.y && pt.y < poly[i].y)) &&
+ pt.x <
+ ((poly[j].x - poly[i].x) * (pt.y - poly[i].y)) /
+ (poly[j].y - poly[i].y) +
+ poly[i].x &&
+ (c = !c);
+ return c;
+ }
//清空画布
clearCanvas() {
- this.points = [];
- this.points2 = [];
- this.circles = [];
- this.circles2 = [];
- this.allpoints = [];
- this.allpoints2 = [];
let canvas = document.getElementById('canvas') as any;
let context = canvas.getContext('2d');
- context.clearRect(0, 0, canvas.width, canvas.height);
- this.copyCanvas?context.putImageData(this.copyCanvas, 0, 0) : null;
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null;
}
- //初始化 canvas画布 点击事件
- initCanvasEvent(canvas) {
- let context = canvas.getContext('2d');
- let html = document.documentElement
- let boxDiv = document.getElementsByClassName("canvasDialog")[0]
- canvas.onmousedown = (e)=>{
- var clickX = e.pageX - canvas.offsetLeft - ((html.clientWidth - boxDiv.clientWidth) / 2);
- var clickY = e.pageY - canvas.offsetTop - ((html.clientHeight - boxDiv.clientHeight) / 2);
- this.downx = clickX
- this.downy = clickY
- if (this.isInt(clickX, clickY)) {
- this.isInOut = true
- return
- } else {
- this.isInOut = false
- }
+ //清除某个标绘
+ clearCanvasItem(e, type) {
+ e.stopPropagation();
+ this.modal.confirm({
+ nzTitle: '确认要清除此标绘吗?',
+ nzOkText: '确定',
+ nzOkType: 'primary',
+ nzOkDanger: true,
+ nzOnOk: () => {
+ // if (type == 'isAllMonitoring') {
+ // //全局的多边形
+ // this.pointsOfmonitor = [];
+ // this.circlesOfmonitor = [];
+ // this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ // this.copyCanvas
+ // ? this.context.putImageData(this.copyCanvas, 0, 0)
+ // : null;
+ // }
+ // this.initMark2(this.canvas, this.ctx); //初始化标绘图形
+ },
+ nzCancelText: '取消',
+ });
+ }
- let index
- let beforeCircles = this.markType? this.circles: this.circles2
- //判断当前点击点是否在已经绘制的圆圈上,如果是执行相关操作,并return,不进入画线的代码
- for (var i = 0; i < beforeCircles.length; i++) {
- let circle = beforeCircles[i];
- //使用勾股定理计算这个点与圆心之间的距离
- var distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2));
-
- // 如果是其他的点,则设置可以拖动
- if (distanceFromCenter <= circle.radius) {
- // 清除之前选择的圆圈
- index = i;
- this.isDragging = true;
- //停止搜索
- return;
- }
- }
- //如果点击新的位置,则进入下面的代码,绘制点
- //context.clearRect(0, 0, canvas.width, canvas.height);
+ //根据已有数据重绘多边形
+ redrawPolygon(data, points, circles, context, color) {
+ data.forEach((element) => {
//遍历数组画圆
- var circle = {
- x: clickX,
- y: clickY,
- radius: 10,
- color: "blue",
- isSelected: false, //拖拽点的标记
- };
- if (this.markType) {
- this.circles.push(circle);
- this.allpoints = JSON.parse(JSON.stringify(this.circles))
- this.circles[0].color = "green";
- } else {
- this.circles2.push(circle);
- this.allpoints2 = JSON.parse(JSON.stringify(this.circles2))
- this.circles2[0].color = "red";
- }
- for (var i = 0; i < beforeCircles.length; i++) {
- let circle = beforeCircles[i];
+ points = JSON.parse(JSON.stringify(circles));
+ circles[0].color = 'white';
+ for (var i = 0; i < circles.length; i++) {
+ let circle = circles[i];
// 绘制圆圈
context.globalAlpha = 0.85;
context.beginPath();
context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
context.fillStyle = circle.color;
- context.strokeStyle = "black";
+ context.strokeStyle = 'red';
context.fill();
context.stroke();
}
// 画线
- var point = {
- x: clickX,
- y: clickY,
- };
- this.markType? this.points.push(point) : this.points2.push(point)
context.beginPath();
context.lineWidth = 3;
//从起始点开始绘制
- let beforePoint = this.markType? this.points: this.points2
- context.moveTo(beforePoint[0].x, beforePoint[0].y);
- for (var i = 0; i < beforePoint.length; i++) {
- context.lineTo(beforePoint[i].x, beforePoint[i].y);
+ context.moveTo(data[0].x, data[0].y);
+ for (var i = 0; i < data.length; i++) {
+ context.lineTo(data[i].x, data[i].y);
}
- context.closePath()
- context.fillStyle = "rgb(2,100,30)";
- context.fill();
- context.strokeStyle = "#9d4dca";
+ context.closePath();
+ context.strokeStyle = color;
context.stroke();
- }
+ });
}
- //判断点位是否在图形区域内
- isInt(x, y) {
- if (this.markType && !this.points[2]) {
- return
- }
- if (!this.markType && !this.points2[2]) {
- return
+ //根据已有数据重绘矩形
+ redrawRectangle(oblongList, context) {
+ oblongList.forEach((element) => {
+ context.strokeStyle = 'orange';
+ context.lineWidth = 3;
+ context.strokeRect(element.x, element.y, element.width, element.height);
+ context.font = '22px Arial';
+ context.fontColor = 'orange';
+ context.fillText('高度:' + element.height, element.x + 3, element.y + 22);
+ });
+ }
+
+ //保存
+ save() {
+ console.log(this.camerasData.dimensionedPointsOfHH);
+ if (!this.camerasData.dimensionedPointsOfHH) {
+ this.camerasData.dimensionedPointsOfHH = {
+ carStopROI: [],
+ intrusionROI: [],
+ cashierROI: [],
+ unloadingROI: [],
+ };
}
- var pt = {
- x: x,
- y: y
+ //进出口
+ if (this.markType === 0) {
+ if (this.carStopROIPoints.length === 0) {
+ this.message.create('warning', '绘制完整后可保存!');
+ return;
+ }
+ this.camerasData.dimensionedPointsOfHH.carStopROI = this.carStopROIPoints;
}
- var poly = this.markType? this.points : this.points2;
- return this.PointInPoly(pt, poly)
- }
+ //卸油区
+ if (this.markType === 2) {
+ if (
+ this.carStopROIPoints.length === 0 ||
+ this.intrusionROIPoints.length === 0 ||
+ this.unloadingROIOblongPoints.length === 0
+ ) {
+ this.message.create('warning', '绘制完整后可保存!');
+ return;
+ }
- //射线法判断点位
- PointInPoly(pt, poly) {
- for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
- ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y))
- && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x)
- && (c = !c);
- return c;
- }
+ this.camerasData.dimensionedPointsOfHH.carStopROI = this.carStopROIPoints;
+ this.camerasData.dimensionedPointsOfHH.intrusionROI =
+ this.intrusionROIPoints;
+ this.camerasData.dimensionedPointsOfHH.unloadingROI =
+ this.unloadingROIOblongPoints;
+ }
+ //便利店
+ if (this.markType === 3) {
+ if (this.cashierROIPoints.length === 0) {
+ this.message.create('warning', '绘制完整后可保存!');
+ return;
+ }
+ this.camerasData.dimensionedPointsOfHH.cashierROI = this.cashierROIPoints;
+ }
- //cneter height
- heightCount() {
- let style: any = {}
- let height = document.documentElement.clientHeight
- style.height = (height - 180) + 'px';
- return style
+ // let paramsData = JSON.parse(JSON.stringify(this.camerasData));
+ // paramsData.dimensionedPointsHH = JSON.stringify(
+ // paramsData.dimensionedPointsHH
+ // );
+ console.log('标点结果', this.camerasData.dimensionedPointsOfHH);
+ // this.http
+ // .put(`/api/Cameras/${this.camerasData.id}/DimensionedPoints`, paramsData)
+ // .subscribe((data) => {
+ // this.message.create('success', '保存成功!');
+ // const isFullScreen = document.fullscreenElement;
+ // if (document.exitFullscreen && isFullScreen) {
+ // //关闭全屏
+ // document.exitFullscreen();
+ // }
+ // this.modal.closeAll();
+ // });
}
-
}
diff --git a/src/app/system-management/system-management.module.ts b/src/app/system-management/system-management.module.ts
index 4bd5bf6..05e7342 100644
--- a/src/app/system-management/system-management.module.ts
+++ b/src/app/system-management/system-management.module.ts
@@ -45,8 +45,35 @@ import { FileComponent } from './condition-monitoring/file/file.component';
import { ScriptComponent } from './status-monitoring/script/script.component';
import { VideoStreamingComponent } from './video-streaming/video-streaming.component';
import { DetailsComponent } from './video-streaming/details/details.component';
+import { NzRadioModule } from 'ng-zorro-antd/radio';
@NgModule({
- declarations: [OrganizationComponent, NavigationComponent, AddorComponent, EditorComponent, AnalysisOfTheHostComponent, AddhostComponent, EdithostComponent, AddcameraComponent, EditcameraComponent, HostConfigComponent, ImageListComponent, ImageLabelComponent, PlottingImageComponent, cameraType, ImageLabel2Component, ConfigFormComponent, ConditionMonitoringComponent, SendFileComponent, ModelComponent, KafkaComponent, StatusMonitoringComponent, FileComponent, ScriptComponent, VideoStreamingComponent, DetailsComponent],
+ declarations: [
+ OrganizationComponent,
+ NavigationComponent,
+ AddorComponent,
+ EditorComponent,
+ AnalysisOfTheHostComponent,
+ AddhostComponent,
+ EdithostComponent,
+ AddcameraComponent,
+ EditcameraComponent,
+ HostConfigComponent,
+ ImageListComponent,
+ ImageLabelComponent,
+ PlottingImageComponent,
+ cameraType,
+ ImageLabel2Component,
+ ConfigFormComponent,
+ ConditionMonitoringComponent,
+ SendFileComponent,
+ ModelComponent,
+ KafkaComponent,
+ StatusMonitoringComponent,
+ FileComponent,
+ ScriptComponent,
+ VideoStreamingComponent,
+ DetailsComponent,
+ ],
imports: [
CommonModule,
SystemRoutingModule,
@@ -69,9 +96,21 @@ import { DetailsComponent } from './video-streaming/details/details.component';
NzCheckboxModule,
NzPageHeaderModule,
NzTabsModule,
- NzPopconfirmModule
+ NzPopconfirmModule,
+ NzRadioModule,
+ ],
+ entryComponents: [
+ AddorComponent,
+ EditorComponent,
+ AddhostComponent,
+ EdithostComponent,
+ AddcameraComponent,
+ EditcameraComponent,
+ SendFileComponent,
+ ModelComponent,
+ FileComponent,
+ ScriptComponent,
+ DetailsComponent,
],
- entryComponents: [AddorComponent, EditorComponent, AddhostComponent, EdithostComponent, AddcameraComponent, EditcameraComponent, SendFileComponent, ModelComponent, FileComponent, ScriptComponent, DetailsComponent]
-
})
-export class SystemManagementModule { }
+export class SystemManagementModule {}