| | |
| | | return (value * 100).toFixed(1) + '%'; |
| | | }, |
| | | /******************setDeviceInfo使用的函数:******************/ |
| | | getAnnulusAwarePoint(trackInfo, x, y, path) { |
| | | return trackInfo.type === 'annulus' |
| | | ? G.snapToAnnulusOuterPath(x, y, path) |
| | | : { x, y }; |
| | | }, |
| | | /** 环穿:把 getPositionAfterMove 的结果压到轨带中线;非环穿原样返回 */ |
| | | applyAnnulusBandCenterToPosition(trackInfo, position) { |
| | | if (!position || trackInfo.type !== 'annulus') { |
| | | return position; |
| | | } |
| | | const c = G.centerAnnulusBandPoint(trackInfo, position.x, position.y, position.path); |
| | | return { ...position, x: c.x, y: c.y }; |
| | | }, |
| | | computeFinalPosition(trackInfo, point, pathList, path, deltaDistance, angle) { |
| | | const position = G.getPositionAfterMove({ point, pathList, path, deltaDistance, angle }); |
| | | return this.applyAnnulusBandCenterToPosition(trackInfo, position); |
| | | }, |
| | | // 环穿条码在总长上的有符号段差 |
| | | calcSignedSegmentDelta(fromBarcode, toBarcode, trackInfo, totalSegmentCount) { |
| | | const from = Number(fromBarcode); |
| | | const to = Number(toBarcode); |
| | |
| | | ) { |
| | | sprite.barcode = device.rgvPos; |
| | | sprite.time = nowMs(); |
| | | let tmpPassedSegmentCount = device.rgvPos - minBarcode; |
| | | const passedSegmentCount = |
| | | tmpPassedSegmentCount < 0 |
| | | ? tmpPassedSegmentCount + totalSegmentCount |
| | | : tmpPassedSegmentCount; |
| | | const passedSegmentCount = this.calcSignedSegmentDelta( |
| | | minBarcode, |
| | | device.rgvPos, |
| | | sprite.trackInfo, |
| | | totalSegmentCount |
| | | ); |
| | | const deltaDistance = (allDistance * passedSegmentCount) / totalSegmentCount; |
| | | const initPath = sprite.path; |
| | | const initMovePoint = this.getAnnulusAwarePoint( |
| | | const initMovePoint = G.snapToAnnulusOuterPath( |
| | | sprite.trackInfo, |
| | | sprite.x, |
| | | sprite.y, |
| | | initPath |
| | | ); |
| | | let mappingInfo = this.computeFinalPosition( |
| | | let mappingInfo = G.computeFinalPosition( |
| | | sprite.trackInfo, |
| | | initMovePoint, |
| | | pathList, |
| | |
| | | sprite.rotation = G.getRotate(mappingInfo, mappingInfo.path) || sprite.rotation; |
| | | sprite.currentAngle = mappingInfo.angle; |
| | | sprite.mappingInfo = mappingInfo; |
| | | const anchorPoint = this.getAnnulusAwarePoint( |
| | | const anchorPoint = G.snapToAnnulusOuterPath( |
| | | sprite.trackInfo, |
| | | mappingInfo.x, |
| | | mappingInfo.y, |
| | |
| | | } else { |
| | | smoothDistance = stepCap; |
| | | } |
| | | const movePointBarcode = this.getAnnulusAwarePoint( |
| | | const movePointBarcode = G.snapToAnnulusOuterPath( |
| | | sprite.trackInfo, |
| | | sprite.x, |
| | | sprite.y, |
| | | path |
| | | ); |
| | | const angle = Math.atan2(sprite.y - path.y, sprite.x - path.x); |
| | | const raw = G.getPositionAfterMove({ |
| | | point: movePointBarcode, |
| | | const p = G.computeFinalPosition( |
| | | sprite.trackInfo, |
| | | movePointBarcode, |
| | | pathList, |
| | | path, |
| | | deltaDistance: smoothDistance, |
| | | smoothDistance, |
| | | angle |
| | | }); |
| | | const p = this.applyAnnulusBandCenterToPosition(sprite.trackInfo, raw); |
| | | ); |
| | | sprite.path = p.path; |
| | | sprite.x = p.x; |
| | | sprite.y = p.y; |
| | | sprite.rotation = G.getRotate(raw, raw.path) || sprite.rotation; |
| | | sprite.rotation = G.getRotate(p, p.path) || sprite.rotation; |
| | | const restDistanceAfter = G.calcDistance({ x: sprite.x, y: sprite.y }, sprite.mappingInfo); |
| | | if (restDistanceAfter <= EPSILON || Math.abs(smoothDistance) >= restDistance - EPSILON) { |
| | | this.finishDeviceMotion(sprite); |
| | |
| | | anchor.totalSegmentCount !== totalSegmentCount; |
| | | if (needResetAnchor) { |
| | | const anchorPath = sprite.path; |
| | | const anchorPoint = this.getAnnulusAwarePoint( |
| | | const anchorPoint = G.snapToAnnulusOuterPath( |
| | | sprite.trackInfo, |
| | | sprite.x, |
| | | sprite.y, |
| | |
| | | const deltaDistance = (allDistance * passedSegmentCount) / totalSegmentCount; |
| | | const path = anchor.path || sprite.path; |
| | | const barcodeMovePoint = { x: anchor.x, y: anchor.y }; |
| | | let finalPosition = this.computeFinalPosition( |
| | | let finalPosition = G.computeFinalPosition( |
| | | sprite.trackInfo, |
| | | barcodeMovePoint, |
| | | pathList, |
| | |
| | | barCodeStart: 0, |
| | | barCodeEnd: 100000, |
| | | deviceList: [ |
| | | { |
| | | valueKey: '', |
| | | deviceNo: '', |
| | | progress: 0, |
| | | deviceLength: '', |
| | | deviceWidth: '' |
| | | } |
| | | // { |
| | | // valueKey: '', |
| | | // deviceNo: '', |
| | | // progress: 0, |
| | | // deviceLength: '', |
| | | // deviceWidth: '' |
| | | // } |
| | | ] |
| | | }; |
| | | }, |
| | |
| | | }, |
| | | getDeviceLengthPlaceholder: function () { |
| | | var box = this.getAutoTrackDeviceBox(); |
| | | return box && box.along ? '默认: ' + box.along : ''; |
| | | return box && box.along ? '参考: ' + box.along : ''; |
| | | }, |
| | | getDeviceWidthPlaceholder: function () { |
| | | var box = this.getAutoTrackDeviceBox(); |
| | | return box && box.across ? '默认: ' + box.across : ''; |
| | | return box && box.across ? '参考: ' + box.across : ''; |
| | | }, |
| | | loadDeviceForm: function (type, value) { |
| | | this.resetDeviceForm(); |
| | |
| | | barCodeStart: 0, |
| | | barCodeEnd: 100000, |
| | | deviceList: [ |
| | | { |
| | | valueKey: '', |
| | | deviceNo: '', |
| | | progress: 0, |
| | | deviceLength: '', |
| | | deviceWidth: '' |
| | | } |
| | | // { |
| | | // valueKey: '', |
| | | // deviceNo: '', |
| | | // progress: 0, |
| | | // deviceLength: '', |
| | | // deviceWidth: '' |
| | | // } |
| | | ], |
| | | ...json |
| | | }; |
| | |
| | | }); |
| | | }, |
| | | addDeviceForm: function () { |
| | | const defaultDeviceBox = this.getAutoTrackDeviceBox(); |
| | | this.deviceForm.deviceList.push({ |
| | | valueKey: '', |
| | | deviceNo: '', |
| | | progress: 0, |
| | | deviceLength: '', |
| | | deviceWidth: '' |
| | | deviceLength: "", |
| | | deviceWidth: "" |
| | | }); |
| | | }, |
| | | applyDeviceForm: function () { |
| | |
| | | if ( |
| | | !this.deviceForm.deviceList || |
| | | this.deviceForm.deviceList.length === 0 || |
| | | this.deviceForm.deviceList.some((item) => item.deviceNo === '') |
| | | this.deviceForm.deviceList.some((item) => item.deviceNo === '' || item.deviceLength === '' || item.deviceWidth === '') |
| | | ) { |
| | | this.showMessage('warning', '设备列表不能为空'); |
| | | return; |
| | |
| | | delete payload.rgvNo; |
| | | self.deviceForm.deviceList.forEach((item) => { |
| | | item.valueKey = valueKey; |
| | | // 允许通过属性面板覆盖默认设备像素尺寸(沿轨道/垂直轨道) |
| | | var deviceLength = toInt(item.deviceLength, 0); |
| | | var deviceWidth = toInt(item.deviceWidth, 0); |
| | | if (deviceLength > 0) { |
| | | item.deviceLength = String(deviceLength); |
| | | } else { |
| | | delete item.deviceLength; |
| | | } |
| | | if (deviceWidth > 0) { |
| | | item.deviceWidth = String(deviceWidth); |
| | | } else { |
| | | delete item.deviceWidth; |
| | | } |
| | | }); |
| | | self.deviceForm.trackId = String(trackId); |
| | | self.deviceForm.barCodeStart = toInt(self.deviceForm.barCodeStart, 0); |
| | |
| | | newElement.value = JSON.stringify({ |
| | | trackId: this.getNextDeviceTrackId(null), |
| | | deviceList: [ |
| | | { |
| | | valueKey: '', |
| | | deviceNo: '', |
| | | progress: 0 |
| | | } |
| | | // { |
| | | // valueKey: '', |
| | | // deviceNo: '', |
| | | // progress: 0 |
| | | // } |
| | | ] |
| | | }); |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * 环穿:把 getPositionAfterMove 等返回的 position 压到轨带中线;非环穿或无效 position 原样返回。 |
| | | * @param {{ type: string }} trackInfo |
| | | * @param {{ x: number, y: number, path?: object }|null|undefined} position |
| | | * @returns {typeof position} |
| | | */ |
| | | function applyAnnulusBandCenterToPosition(trackInfo, position) { |
| | | if (!position || !trackInfo || trackInfo.type !== 'annulus') { |
| | | return position; |
| | | } |
| | | var c = centerAnnulusBandPoint(trackInfo, position.x, position.y, position.path); |
| | | return Object.assign({}, position, { x: c.x, y: c.y }); |
| | | } |
| | | |
| | | /** |
| | | * 沿 pathList 移动后再对环穿做轨带中线修正(与 getPositionAfterMove + applyAnnulusBandCenterToPosition 等价)。 |
| | | * @param {{ type: string }} trackInfo |
| | | * @param {{ x: number, y: number }} point 起点;环穿上应在外圈 path 上 |
| | | * @param {object[]} pathList |
| | | * @param {object} path |
| | | * @param {number} deltaDistance |
| | | * @param {number} [angle] |
| | | * @returns {{ x: number, y: number, path: object, angle?: number }} 与 getPositionAfterMove 返回形态一致 |
| | | */ |
| | | function computeFinalPosition(trackInfo, point, pathList, path, deltaDistance, angle) { |
| | | var position = getPositionAfterMove({ |
| | | point: point, |
| | | pathList: pathList, |
| | | path: path, |
| | | deltaDistance: deltaDistance, |
| | | angle: angle |
| | | }); |
| | | return applyAnnulusBandCenterToPosition(trackInfo, position); |
| | | } |
| | | |
| | | /** |
| | | * 将坐标压回环穿外圈 path(直线段投影、圆弧段落到半径上)。 |
| | | * sprite 已做 centerAnnulusBandPoint 时不能直接作为 getPositionAfterMove 的起点,否则会沿「点→段终点」斜移漂移。 |
| | | * @param {number} x |
| | |
| | | * @param {{ type: string, startX?: number, startY?: number, x?: number, y?: number, radius?: number }|null|undefined} path |
| | | * @returns {{ x: number, y: number }} |
| | | */ |
| | | function snapToAnnulusOuterPath(x, y, path) { |
| | | if (!path) { |
| | | function snapToAnnulusOuterPath(trackInfo, x, y, path) { |
| | | if (!path || trackInfo.type !== 'annulus') { |
| | | return { x: x, y: y }; |
| | | } |
| | | if (path.type === 'line') { |
| | |
| | | snapToAnnulusOuterPath: snapToAnnulusOuterPath, |
| | | startDrawSmoothedPath: startDrawSmoothedPath, |
| | | getRotate: getRotate, |
| | | computeFinalPosition:computeFinalPosition, |
| | | applyAnnulusBandCenterToPosition:applyAnnulusBandCenterToPosition, |
| | | drawCrnDeviceGraphics: drawCrnDeviceGraphics, |
| | | drawRgvDeviceGraphics: drawRgvDeviceGraphics |
| | | }; |