kfb-view 3.2.3 → 3.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/kfb-view.js +1 -1
- package/package.json +1 -1
- package/src/components/area/index.js +134 -152
- package/src/components/board/index.js +9 -30
- package/src/components/common/common.js +43 -57
- package/src/components/graduation/index.js +6 -5
- package/src/components/shape/index.js +10 -6
- package/src/tool/Combination.js +14 -4
- package/src/tool/Ellipse.js +12 -13
- package/src/tool/Font.js +4 -3
- package/src/tool/Rectangle.js +10 -23
- package/src/util/calculate.js +78 -52
- package/src/util/index.js +0 -17
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import {Thumb} from '../../tool/Thumb';
|
|
2
2
|
import {
|
|
3
|
-
acreage,
|
|
4
|
-
getAngle,
|
|
5
|
-
perimeter,
|
|
6
3
|
pointsToRegion,
|
|
7
4
|
getRectPoint,
|
|
8
5
|
isPointInEllipse,
|
|
9
6
|
isPointInMatrix,
|
|
10
7
|
isPointInPolygon,
|
|
11
8
|
calculatePolygonArea,
|
|
9
|
+
getUnitNumber,
|
|
12
10
|
} from '../../util/calculate';
|
|
13
11
|
import {Point, Rect} from '../../plugin/openseadragon/openseadragon';
|
|
14
12
|
import {
|
|
@@ -19,7 +17,6 @@ import {
|
|
|
19
17
|
LINE,
|
|
20
18
|
RECTANGLE,
|
|
21
19
|
} from '../../const/mark';
|
|
22
|
-
import {getUnitNumber} from '../../util';
|
|
23
20
|
|
|
24
21
|
/**
|
|
25
22
|
* 通用方法类
|
|
@@ -93,6 +90,9 @@ export class ViewerCommon {
|
|
|
93
90
|
* @return {boolean}
|
|
94
91
|
*/
|
|
95
92
|
isContainerInRegion(point, {region, tool, points, isClose}) {
|
|
93
|
+
if (tool === POLYGON && isClose) {
|
|
94
|
+
return isPointInPolygon(point, points);
|
|
95
|
+
}
|
|
96
96
|
const p1 = {x: region.x, y: region.y};
|
|
97
97
|
const p2 = {x: region.x + region.width, y: region.y};
|
|
98
98
|
const p3 = {x: region.x, y: region.y + region.height};
|
|
@@ -107,9 +107,6 @@ export class ViewerCommon {
|
|
|
107
107
|
if (tool === RECTANGLE) {
|
|
108
108
|
return isPointInMatrix(p1, p2, p3, p4, point);
|
|
109
109
|
}
|
|
110
|
-
if (tool === POLYGON && isClose) {
|
|
111
|
-
return isPointInPolygon(point, points);
|
|
112
|
-
}
|
|
113
110
|
return false;
|
|
114
111
|
}
|
|
115
112
|
|
|
@@ -178,6 +175,23 @@ export class ViewerCommon {
|
|
|
178
175
|
});
|
|
179
176
|
}
|
|
180
177
|
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 转化图像点数组到元素坐标点数组
|
|
181
|
+
* @param {Array} points
|
|
182
|
+
* @return {{}[]}
|
|
183
|
+
*/
|
|
184
|
+
viewerElementToImagePoints(points) {
|
|
185
|
+
return (points || []).map((point) => {
|
|
186
|
+
const p = this.viewerElementToImageCoordinates(point.x, point.y);
|
|
187
|
+
return {
|
|
188
|
+
canMove: point.canMove,
|
|
189
|
+
x: p.x,
|
|
190
|
+
y: p.y,
|
|
191
|
+
};
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
181
195
|
/**
|
|
182
196
|
* 返回图像倍率
|
|
183
197
|
* @param {boolean} current Pass true for the current location; defaults to false (target location).
|
|
@@ -224,48 +238,22 @@ export class ViewerCommon {
|
|
|
224
238
|
};
|
|
225
239
|
const w = Math.abs(endPoint.x - startPoint.x);
|
|
226
240
|
const h = Math.abs(endPoint.y - startPoint.y);
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
y: (endPoint.y + startPoint.y) / 2,
|
|
230
|
-
};
|
|
231
|
-
const deg = getAngle(startPoint, {...startPoint, x: startPoint.x + 1},
|
|
232
|
-
endPoint);
|
|
233
|
-
const p = this.imageToViewerElementCoordinates(center.x,
|
|
234
|
-
center.y);
|
|
235
|
-
let distY = -50;
|
|
236
|
-
let distX = -50;
|
|
237
|
-
if (endPoint.y < startPoint.y && endPoint.x > startPoint.x) {
|
|
238
|
-
distY = -50;
|
|
239
|
-
distX = -50;
|
|
240
|
-
}
|
|
241
|
-
if (endPoint.y < startPoint.y && endPoint.x < startPoint.x) {
|
|
242
|
-
distY = -10;
|
|
243
|
-
distX = 50;
|
|
244
|
-
}
|
|
245
|
-
if (endPoint.y > startPoint.y && endPoint.x > startPoint.x) {
|
|
246
|
-
distY = 10;
|
|
247
|
-
distX = -50;
|
|
248
|
-
}
|
|
249
|
-
if (endPoint.y > startPoint.y && endPoint.x < startPoint.x) {
|
|
250
|
-
distY = 50;
|
|
251
|
-
distX = 80;
|
|
252
|
-
}
|
|
241
|
+
const p = this.imageToViewerElementCoordinates(endPoint.x,
|
|
242
|
+
endPoint.y);
|
|
253
243
|
content = {
|
|
254
|
-
left: p.x +
|
|
255
|
-
top: p.y
|
|
256
|
-
angle:
|
|
244
|
+
left: p.x + 10 * scale,
|
|
245
|
+
top: p.y,
|
|
246
|
+
angle: 0,
|
|
257
247
|
texts: [
|
|
258
|
-
`长:${this.getUnitNumber(
|
|
248
|
+
`长:${this.getUnitNumber(Math.sqrt(w * w + h * h) * this.options.imageCapRes)}`],
|
|
259
249
|
};
|
|
260
250
|
}
|
|
261
251
|
break;
|
|
262
252
|
case ELLIPSE: {
|
|
263
253
|
const w = Math.abs(endPoint.x - startPoint.x) / 2;
|
|
264
254
|
const h = Math.abs(endPoint.y - startPoint.y) / 2;
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
const ac = acreage(ELLIPSE, startPoint, endPoint,
|
|
268
|
-
this.options.imageCapRes).toFixed(2);
|
|
255
|
+
const a = (w > h ? w : h) * this.options.imageCapRes;
|
|
256
|
+
const b = (w > h ? h : w) * this.options.imageCapRes;
|
|
269
257
|
const rightTop = getRectPoint(startPoint, endPoint)[2];
|
|
270
258
|
const p = this.imageToViewerElementCoordinates(rightTop.x,
|
|
271
259
|
rightTop.y);
|
|
@@ -274,20 +262,18 @@ export class ViewerCommon {
|
|
|
274
262
|
top: p.y,
|
|
275
263
|
angle: 0,
|
|
276
264
|
texts: [
|
|
277
|
-
`长轴:${this.getUnitNumber(
|
|
278
|
-
`短轴:${this.getUnitNumber(
|
|
279
|
-
`周长:${this.getUnitNumber(
|
|
280
|
-
`面积:${this.getUnitNumber(
|
|
265
|
+
`长轴:${this.getUnitNumber(a)}`,
|
|
266
|
+
`短轴:${this.getUnitNumber(b)}`,
|
|
267
|
+
`周长:${this.getUnitNumber(4 * (a - b) + 2 * Math.PI * b)}`,
|
|
268
|
+
`面积:${this.getUnitNumber(Math.PI * a * b / this.options.binary)}²`],
|
|
281
269
|
};
|
|
282
270
|
}
|
|
283
271
|
break;
|
|
284
272
|
case RECTANGLE: {
|
|
285
|
-
const w = Math.abs(endPoint.x - startPoint.x);
|
|
286
|
-
const h = Math.abs(endPoint.y - startPoint.y);
|
|
287
|
-
const pt =
|
|
288
|
-
|
|
289
|
-
const ac = acreage(RECTANGLE, startPoint, endPoint,
|
|
290
|
-
this.options.imageCapRes).toFixed(2);
|
|
273
|
+
const w = Math.abs(endPoint.x - startPoint.x) * this.options.imageCapRes;
|
|
274
|
+
const h = Math.abs(endPoint.y - startPoint.y) * this.options.imageCapRes;
|
|
275
|
+
const pt = (w + h) * 2;
|
|
276
|
+
const ac = w * h / this.options.binary;
|
|
291
277
|
const rightTop = getRectPoint(startPoint, endPoint)[2];
|
|
292
278
|
const p = this.imageToViewerElementCoordinates(rightTop.x,
|
|
293
279
|
rightTop.y);
|
|
@@ -296,8 +282,8 @@ export class ViewerCommon {
|
|
|
296
282
|
top: p.y,
|
|
297
283
|
angle: 0,
|
|
298
284
|
texts: [
|
|
299
|
-
`长:${this.getUnitNumber(
|
|
300
|
-
`宽:${this.getUnitNumber(
|
|
285
|
+
`长:${this.getUnitNumber(w)}`,
|
|
286
|
+
`宽:${this.getUnitNumber(h)}`,
|
|
301
287
|
`周长:${this.getUnitNumber(pt)}`,
|
|
302
288
|
`面积:${this.getUnitNumber(ac)}²`],
|
|
303
289
|
};
|
|
@@ -319,8 +305,8 @@ export class ViewerCommon {
|
|
|
319
305
|
angle: 0,
|
|
320
306
|
texts: [
|
|
321
307
|
`周长:${this.getUnitNumber((pt * this.options.imageCapRes).toFixed(2))}`,
|
|
322
|
-
`面积:${this.getUnitNumber(
|
|
323
|
-
this.options.imageCapRes).
|
|
308
|
+
`面积:${this.getUnitNumber(
|
|
309
|
+
calculatePolygonArea(points, this.options.imageCapRes) / this.options.binary)}²`],
|
|
324
310
|
};
|
|
325
311
|
}
|
|
326
312
|
break;
|
|
@@ -343,8 +329,8 @@ export class ViewerCommon {
|
|
|
343
329
|
};
|
|
344
330
|
}
|
|
345
331
|
|
|
346
|
-
getUnitNumber(number) {
|
|
347
|
-
return getUnitNumber(number, this.options.units, this.options.binary);
|
|
332
|
+
getUnitNumber(number, index) {
|
|
333
|
+
return getUnitNumber(number, this.options.units, this.options.binary, index);
|
|
348
334
|
}
|
|
349
335
|
|
|
350
336
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ViewerCommon} from '../common/common';
|
|
2
2
|
import {EVENT_GRADUATION_CHANGE} from '../../const/event';
|
|
3
|
-
import {getUnitNumber} from '../../util';
|
|
3
|
+
import {getUnitNumber} from '../../util/calculate';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* 刻度线
|
|
@@ -17,7 +17,7 @@ export class Graduation extends ViewerCommon {
|
|
|
17
17
|
constructor({viewer, canvas, cache, options}) {
|
|
18
18
|
super(viewer, canvas, cache, options);
|
|
19
19
|
this.microns = options.microns ||
|
|
20
|
-
[5000, 2000, 1500, 1250, 1000, 800, 500, 400, 250, 200, 150, 125, 100, 80, 60, 40, 20, 10, 8, 5];
|
|
20
|
+
[5000, 2000, 1500, 1250, 1000, 800, 500, 400, 250, 200, 150, 125, 100, 80, 60, 40, 20, 10, 8, 5, 4, 2, 1];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -25,8 +25,9 @@ export class Graduation extends ViewerCommon {
|
|
|
25
25
|
*/
|
|
26
26
|
change() {
|
|
27
27
|
const microns = this.microns;
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const startPoint = this.viewerElementToImageCoordinates(0, 0);
|
|
29
|
+
const endPoint = this.viewerElementToImageCoordinates(50, 0);
|
|
30
|
+
const max = endPoint.distanceTo(startPoint) * this.options.imageCapRes;
|
|
30
31
|
const index = this.microns.findIndex((i) => i <= max);
|
|
31
32
|
if (!~index) {
|
|
32
33
|
this.setScaleLine(microns[microns.length - 1],
|
|
@@ -45,7 +46,7 @@ export class Graduation extends ViewerCommon {
|
|
|
45
46
|
setScaleLine(txt, px) {
|
|
46
47
|
const startPoint = this.imageToViewerElementCoordinates(0, 0);
|
|
47
48
|
const endPoint = this.imageToViewerElementCoordinates(px, 0);
|
|
48
|
-
const width =
|
|
49
|
+
const width = endPoint.distanceTo(startPoint);
|
|
49
50
|
if (this.options.custom) {
|
|
50
51
|
this.mitt.$emit(EVENT_GRADUATION_CHANGE, {width, txt});
|
|
51
52
|
} else {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HAS_NO_FILL_TYPES,
|
|
3
|
-
|
|
3
|
+
IMAGE,
|
|
4
4
|
MARKS, POINT_TYPES, POLYGON, REGION_TYPES,
|
|
5
5
|
} from '../../const/mark';
|
|
6
6
|
import {ViewerCommon} from '../common/common';
|
|
@@ -51,7 +51,7 @@ export class Shape extends ViewerCommon {
|
|
|
51
51
|
change() {
|
|
52
52
|
this.clearCanvas();
|
|
53
53
|
const bounds = this.viewport.viewportToImageRectangle(
|
|
54
|
-
this.viewport.
|
|
54
|
+
this.viewport.getBoundsNoRotate());
|
|
55
55
|
// strokeStyle, lineWidth, fillStyle 相同认为是一个路径下的图形,一起绘制,优化性能
|
|
56
56
|
const sameFixWidthLabel = {}; // star, flag, star, font lineWidth固定为2
|
|
57
57
|
const sameNormalLabel = {};
|
|
@@ -173,7 +173,7 @@ export class Shape extends ViewerCommon {
|
|
|
173
173
|
}, item.child.map(({points, tool}) => ({
|
|
174
174
|
points: this.imageToViewerElementPoints(points),
|
|
175
175
|
tool,
|
|
176
|
-
})), this.
|
|
176
|
+
})), this.getAngle(item.angle));
|
|
177
177
|
});
|
|
178
178
|
} else {
|
|
179
179
|
this.delaytimer = setTimeout(() => {
|
|
@@ -184,16 +184,20 @@ export class Shape extends ViewerCommon {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
getAngle(angle) {
|
|
188
|
+
const currentAngle = this.viewport.getRotation() % 360;
|
|
189
|
+
return angle ? angle > currentAngle ? currentAngle - angle + 360 : currentAngle - angle : currentAngle;
|
|
190
|
+
}
|
|
191
|
+
|
|
187
192
|
drawLabel(item) {
|
|
188
193
|
item.viewerElementPoints = this.imageToViewerElementPoints(item.points);
|
|
189
194
|
const points = item.viewerElementPoints;
|
|
190
195
|
this[item.tool].setContent(this.canvas, item);
|
|
191
196
|
if (REGION_TYPES.includes(item.tool)) {
|
|
192
|
-
this[item.tool].draw(points, this.
|
|
193
|
-
this.imageToViewerElementRectangle(item.region));
|
|
197
|
+
this[item.tool].draw(points, this.getAngle(item.angle));
|
|
194
198
|
} else {
|
|
195
199
|
const scale = this.getImageZoom(true) / item.scale;
|
|
196
|
-
this[item.tool].draw(points, scale);
|
|
200
|
+
this[item.tool].draw(points, scale, this.getAngle(item.angle));
|
|
197
201
|
}
|
|
198
202
|
}
|
|
199
203
|
}
|
package/src/tool/Combination.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Brush} from './Brush';
|
|
2
2
|
import {POLYGON, ELLIPSE, RECTANGLE} from '../const/mark';
|
|
3
|
-
import {pointsToRegion} from '../util/calculate';
|
|
3
|
+
import {getRectPoints, pointsToRegion} from '../util/calculate';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* 曲线类
|
|
@@ -17,16 +17,23 @@ class Combination extends Brush {
|
|
|
17
17
|
*/
|
|
18
18
|
draw(parent, children, rotation = 0) {
|
|
19
19
|
const ctx = this.canvas.getContext('2d');
|
|
20
|
-
|
|
20
|
+
let {tool, points} = parent;
|
|
21
21
|
ctx.beginPath();
|
|
22
22
|
ctx.save();
|
|
23
|
+
if (points.length === 2) {
|
|
24
|
+
points = getRectPoints(points);
|
|
25
|
+
}
|
|
23
26
|
const region = pointsToRegion(points);
|
|
24
27
|
const centerPoint = {
|
|
25
28
|
x: region.x + region.width / 2,
|
|
26
29
|
y: region.y + region.height / 2,
|
|
27
30
|
};
|
|
28
31
|
ctx.translate(centerPoint.x, centerPoint.y);
|
|
29
|
-
|
|
32
|
+
if (rotation < 0) {
|
|
33
|
+
rotation += 360;
|
|
34
|
+
}
|
|
35
|
+
const _rotation = rotation % 360;
|
|
36
|
+
ctx.rotate(_rotation * Math.PI / 180);
|
|
30
37
|
if (tool === POLYGON) {
|
|
31
38
|
ctx.drawPolygon(points.map((p) => ({
|
|
32
39
|
x: p.x - centerPoint.x,
|
|
@@ -48,6 +55,9 @@ class Combination extends Brush {
|
|
|
48
55
|
ctx.closePath();
|
|
49
56
|
ctx.restore();
|
|
50
57
|
children.forEach(({tool, points}) => {
|
|
58
|
+
if (points.length === 2) {
|
|
59
|
+
points = getRectPoints(points);
|
|
60
|
+
}
|
|
51
61
|
ctx.save();
|
|
52
62
|
const region = pointsToRegion(points);
|
|
53
63
|
const centerPoint = {
|
|
@@ -55,7 +65,7 @@ class Combination extends Brush {
|
|
|
55
65
|
y: region.y + region.height / 2,
|
|
56
66
|
};
|
|
57
67
|
ctx.translate(centerPoint.x, centerPoint.y);
|
|
58
|
-
ctx.rotate(
|
|
68
|
+
ctx.rotate(_rotation * Math.PI / 180);
|
|
59
69
|
if (tool === POLYGON) {
|
|
60
70
|
ctx.drawPolygon(points.map((p) => ({
|
|
61
71
|
x: p.x - centerPoint.x,
|
package/src/tool/Ellipse.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Brush} from './Brush';
|
|
2
|
+
import {getDistance, getRectPoints} from '../util/calculate';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* 椭圆类
|
|
@@ -18,9 +19,8 @@ class Ellipse extends Brush {
|
|
|
18
19
|
* @param {number} points[].x - 绘制的点x坐标
|
|
19
20
|
* @param {number} points[].y - 绘制的点y坐标
|
|
20
21
|
* @param {number} rotation
|
|
21
|
-
* @param {Object} region
|
|
22
22
|
*/
|
|
23
|
-
draw(points, rotation = 0
|
|
23
|
+
draw(points, rotation = 0) {
|
|
24
24
|
const startPoint = points[0];
|
|
25
25
|
const endPoint = points[points.length - 1];
|
|
26
26
|
const ctx = this.canvas.getContext('2d');
|
|
@@ -29,24 +29,23 @@ class Ellipse extends Brush {
|
|
|
29
29
|
if (this.options.fillStyle) {
|
|
30
30
|
ctx.fillStyle = this.options.fillStyle;
|
|
31
31
|
}
|
|
32
|
+
if (points.length === 2) {
|
|
33
|
+
points = getRectPoints(points);
|
|
34
|
+
}
|
|
32
35
|
ctx.save();
|
|
33
36
|
const centerPoint = {
|
|
34
37
|
x: (startPoint.x + endPoint.x) / 2,
|
|
35
38
|
y: (startPoint.y + endPoint.y) / 2,
|
|
36
39
|
};
|
|
37
|
-
const width =
|
|
38
|
-
|
|
39
|
-
Math.abs(endPoint.x - startPoint.x);
|
|
40
|
-
const height = region?.height ?
|
|
41
|
-
Math.abs(region.height) :
|
|
42
|
-
Math.abs(endPoint.y - startPoint.y);
|
|
40
|
+
const width = getDistance(points[1], points[0]);
|
|
41
|
+
const height = getDistance(points[2], points[0]);
|
|
43
42
|
ctx.translate(centerPoint.x, centerPoint.y);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
ctx.drawOval(0, 0, width / 2, height / 2);
|
|
47
|
-
} else {
|
|
48
|
-
ctx.drawOval(0, 0, height / 2, width / 2);
|
|
43
|
+
if (rotation < 0) {
|
|
44
|
+
rotation += 360;
|
|
49
45
|
}
|
|
46
|
+
const _rotation = rotation % 360;
|
|
47
|
+
ctx.rotate(_rotation * Math.PI / 180);
|
|
48
|
+
ctx.drawOval(0, 0, width / 2, height / 2);
|
|
50
49
|
ctx.restore();
|
|
51
50
|
}
|
|
52
51
|
}
|
package/src/tool/Font.js
CHANGED
|
@@ -18,16 +18,17 @@ class Font extends Brush {
|
|
|
18
18
|
* @param {number} points[].x - 绘制的点x坐标
|
|
19
19
|
* @param {number} points[].y - 绘制的点y坐标
|
|
20
20
|
* @param {number=} scale
|
|
21
|
+
* @param {number} rotation
|
|
21
22
|
*/
|
|
22
|
-
draw(points, scale = 1) {
|
|
23
|
+
draw(points, scale = 1, rotation = 0) {
|
|
23
24
|
const point = points[0];
|
|
24
|
-
const angle = this.options.angle || 0;
|
|
25
25
|
const text = this.options.text || '编辑文字';
|
|
26
26
|
const ctx = this.canvas.getContext('2d');
|
|
27
27
|
ctx.fillStyle = this.options.strokeStyle;
|
|
28
28
|
ctx.save();
|
|
29
|
+
const _rotation = rotation % 360;
|
|
29
30
|
ctx.translate(point.x, point.y);
|
|
30
|
-
ctx.rotate(
|
|
31
|
+
ctx.rotate(_rotation * Math.PI / 180);
|
|
31
32
|
ctx.scale(scale, scale);
|
|
32
33
|
ctx.font = `${this.options.fontSize}px Arial`;
|
|
33
34
|
const texts = text.split('\n');
|
package/src/tool/Rectangle.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Brush} from './Brush';
|
|
2
|
+
import {getRectPoints} from '../util/calculate';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* 矩形类
|
|
@@ -17,12 +18,11 @@ class Rectangle extends Brush {
|
|
|
17
18
|
* @param {Object[]} points - 绘制的点
|
|
18
19
|
* @param {number} points[].x - 绘制的点x坐标
|
|
19
20
|
* @param {number} points[].y - 绘制的点y坐标
|
|
20
|
-
* @param {number} rotation
|
|
21
|
-
* @param {Object} region
|
|
22
21
|
*/
|
|
23
|
-
draw(points
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
draw(points) {
|
|
23
|
+
if (points.length === 2) {
|
|
24
|
+
points = getRectPoints(points);
|
|
25
|
+
}
|
|
26
26
|
const ctx = this.canvas.getContext('2d');
|
|
27
27
|
ctx.lineWidth = this.options.lineWidth;
|
|
28
28
|
ctx.strokeStyle = this.options.strokeStyle;
|
|
@@ -30,24 +30,11 @@ class Rectangle extends Brush {
|
|
|
30
30
|
ctx.fillStyle = this.options.fillStyle;
|
|
31
31
|
}
|
|
32
32
|
ctx.save();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Math.abs(region.width) :
|
|
39
|
-
Math.abs(endPoint.x - startPoint.x);
|
|
40
|
-
const height = region?.height ?
|
|
41
|
-
Math.abs(region.height) :
|
|
42
|
-
Math.abs(endPoint.y - startPoint.y);
|
|
43
|
-
ctx.translate(centerPoint.x, centerPoint.y);
|
|
44
|
-
if (rotation < 90 && rotation >= 0 || rotation > 180 && rotation < 270) {
|
|
45
|
-
ctx.rotate(rotation * Math.PI / 180);
|
|
46
|
-
ctx.rect(-width / 2, -height / 2, width, height);
|
|
47
|
-
} else {
|
|
48
|
-
ctx.rotate(rotation * Math.PI / 180);
|
|
49
|
-
ctx.rect(-height / 2, -width / 2, height, width);
|
|
50
|
-
}
|
|
33
|
+
ctx.moveTo(points[0].x, points[0].y);
|
|
34
|
+
ctx.lineTo(points[1].x, points[1].y);
|
|
35
|
+
ctx.lineTo(points[3].x, points[3].y);
|
|
36
|
+
ctx.lineTo(points[2].x, points[2].y);
|
|
37
|
+
ctx.lineTo(points[0].x, points[0].y);
|
|
51
38
|
ctx.restore();
|
|
52
39
|
}
|
|
53
40
|
}
|
package/src/util/calculate.js
CHANGED
|
@@ -51,6 +51,43 @@ function getRectPoint(startPoint, endPoint, deg = 0) {
|
|
|
51
51
|
}];
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* 通过起始点和结束点获取矩形中的9个点
|
|
56
|
+
* @param {Object} points
|
|
57
|
+
* @param {number=} deg
|
|
58
|
+
* @return {*[]}
|
|
59
|
+
*/
|
|
60
|
+
function getRectPointV2(points, deg = 0) {
|
|
61
|
+
if (points.length === 2) {
|
|
62
|
+
return getRectPoint(points[0], points[1], deg);
|
|
63
|
+
}
|
|
64
|
+
const centerX = (points[0].x + points[3].x) / 2;
|
|
65
|
+
const centerY = (points[0].y + points[3].y) / 2;
|
|
66
|
+
return [
|
|
67
|
+
points[0],
|
|
68
|
+
{
|
|
69
|
+
x: (points[1].x + points[0].x) / 2,
|
|
70
|
+
y: (points[1].y + points[0].y) / 2,
|
|
71
|
+
},
|
|
72
|
+
points[1],
|
|
73
|
+
{
|
|
74
|
+
x: (points[2].x + points[0].x) / 2,
|
|
75
|
+
y: (points[2].y + points[0].y) / 2,
|
|
76
|
+
}, {
|
|
77
|
+
x: centerX,
|
|
78
|
+
y: centerY,
|
|
79
|
+
}, {
|
|
80
|
+
x: (points[1].x + points[3].x) / 2,
|
|
81
|
+
y: (points[1].y + points[3].y) / 2,
|
|
82
|
+
},
|
|
83
|
+
points[2],
|
|
84
|
+
{
|
|
85
|
+
x: (points[2].x + points[3].x) / 2,
|
|
86
|
+
y: (points[2].y + points[3].y) / 2,
|
|
87
|
+
},
|
|
88
|
+
points[3]];
|
|
89
|
+
}
|
|
90
|
+
|
|
54
91
|
/*
|
|
55
92
|
* 叉乘计算公式 a×b =(x1y2-x2y1)
|
|
56
93
|
* @param {Object} p1
|
|
@@ -239,6 +276,14 @@ function pointsToRegion(points) {
|
|
|
239
276
|
height: points[1].y - points[0].y,
|
|
240
277
|
};
|
|
241
278
|
}
|
|
279
|
+
if (points.length === 4) {
|
|
280
|
+
return {
|
|
281
|
+
x: points[0].x,
|
|
282
|
+
y: points[0].y,
|
|
283
|
+
width: getDistance(points[1], points[0]) * (points[0].x < points[1].x ? 1 : -1),
|
|
284
|
+
height: getDistance(points[2], points[0]) * (points[0].y < points[2].y ? 1 : -1),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
242
287
|
const sortPointX = [...points].sort((a, b) => a.x - b.x);
|
|
243
288
|
const sortPointY = [...points].sort((a, b) => a.y - b.y);
|
|
244
289
|
const startPoint = {x: sortPointX[0].x, y: sortPointY[0].y};
|
|
@@ -334,6 +379,22 @@ function getPoint(cen, first, deg) {
|
|
|
334
379
|
};
|
|
335
380
|
}
|
|
336
381
|
|
|
382
|
+
/**
|
|
383
|
+
* 通过两个点计算矩形的四个点
|
|
384
|
+
* @param {array} points
|
|
385
|
+
* @return {{x: *, y: *}}
|
|
386
|
+
* */
|
|
387
|
+
function getRectPoints(points) {
|
|
388
|
+
return [
|
|
389
|
+
points[0], {
|
|
390
|
+
x: points[1].x,
|
|
391
|
+
y: points[0].y,
|
|
392
|
+
}, {
|
|
393
|
+
x: points[0].x,
|
|
394
|
+
y: points[1].y,
|
|
395
|
+
}, points[1]];
|
|
396
|
+
}
|
|
397
|
+
|
|
337
398
|
/**
|
|
338
399
|
* 计算三点之间的夹角
|
|
339
400
|
* @param {object} cen
|
|
@@ -372,29 +433,6 @@ function getDistance(p1, p2) {
|
|
|
372
433
|
return Math.sqrt(distX + distY);
|
|
373
434
|
}
|
|
374
435
|
|
|
375
|
-
/**
|
|
376
|
-
* 几何图形的面积
|
|
377
|
-
* @param {string} type
|
|
378
|
-
* @param {Object} startPoint
|
|
379
|
-
* @param {Object} endPoint
|
|
380
|
-
* @param {number} imageCapRes 像素转微米系数
|
|
381
|
-
* @return {number}
|
|
382
|
-
*/
|
|
383
|
-
function acreage(type, startPoint, endPoint, imageCapRes = 1) {
|
|
384
|
-
let ag = 0;
|
|
385
|
-
const distX = Math.abs(endPoint.x - startPoint.x) * imageCapRes;
|
|
386
|
-
const distY = Math.abs(endPoint.y - startPoint.y) * imageCapRes;
|
|
387
|
-
if (type === 'Rectangle') {
|
|
388
|
-
ag = distX * distY / 2;
|
|
389
|
-
}
|
|
390
|
-
if (type === 'Ellipse') {
|
|
391
|
-
ag = distX * distY / 4 * Math.PI;
|
|
392
|
-
}
|
|
393
|
-
/* if (type === 'polygon') {
|
|
394
|
-
}*/
|
|
395
|
-
return ag;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
436
|
function calculatePolygonArea(points, ratio) {
|
|
399
437
|
const numVertices = points.length;
|
|
400
438
|
|
|
@@ -421,38 +459,25 @@ function calculatePolygonArea(points, ratio) {
|
|
|
421
459
|
return Math.abs(area / 2);
|
|
422
460
|
}
|
|
423
461
|
|
|
424
|
-
|
|
425
|
-
*
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
*/
|
|
432
|
-
function perimeter(type, startPoint, endPoint, imageCapRes = 1) {
|
|
433
|
-
let pt = 0;
|
|
434
|
-
const distX = Math.abs(endPoint.x - startPoint.x) * imageCapRes;
|
|
435
|
-
const distY = Math.abs(endPoint.y - startPoint.y) * imageCapRes;
|
|
436
|
-
if (type === 'Line' || type === 'Arrow') {
|
|
437
|
-
pt = Math.sqrt(Math.pow(distX, 2) + Math.pow(distY, 2));
|
|
462
|
+
const getRandomId = () => {
|
|
463
|
+
return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
function getUnitNumber(number, units, binary, index = 0) {
|
|
467
|
+
if (index) {
|
|
468
|
+
return (number / Math.pow(binary, index)).toFixed(2) / 1 + units[index];
|
|
438
469
|
}
|
|
439
|
-
|
|
440
|
-
|
|
470
|
+
let i = number;
|
|
471
|
+
while (i >= binary) {
|
|
472
|
+
i = i / binary;
|
|
473
|
+
index++;
|
|
441
474
|
}
|
|
442
|
-
if (
|
|
443
|
-
|
|
444
|
-
const b = (distX >= distY ? distY : distX) / 2;
|
|
445
|
-
pt = 4 * (a - b) + 2 * Math.PI * b;
|
|
475
|
+
if (!units[index]) {
|
|
476
|
+
index = units.length - 1;
|
|
446
477
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}*/
|
|
450
|
-
return pt;
|
|
478
|
+
return (number / Math.pow(binary, index)).toFixed(2) / 1 + units[index];
|
|
451
479
|
}
|
|
452
480
|
|
|
453
|
-
const getRandomId = () => {
|
|
454
|
-
return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
|
|
455
|
-
};
|
|
456
481
|
|
|
457
482
|
export {
|
|
458
483
|
getRectPoint,
|
|
@@ -465,11 +490,12 @@ export {
|
|
|
465
490
|
isPointInLine,
|
|
466
491
|
isNegNumber,
|
|
467
492
|
baseNumber,
|
|
468
|
-
acreage,
|
|
469
|
-
perimeter,
|
|
470
493
|
getPoint,
|
|
471
494
|
getAngle,
|
|
472
495
|
getDistance,
|
|
473
496
|
calculatePolygonArea,
|
|
474
497
|
getRandomId,
|
|
498
|
+
getRectPoints,
|
|
499
|
+
getRectPointV2,
|
|
500
|
+
getUnitNumber,
|
|
475
501
|
};
|
package/src/util/index.js
CHANGED
|
@@ -64,26 +64,9 @@ function delayedTrigger(callback, time = 1000) {
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
function getUnitNumber(number, units, binary, index = 0) {
|
|
68
|
-
if (index) {
|
|
69
|
-
return (number / Math.pow(binary, index)).toFixed(2) / 1 + units[index];
|
|
70
|
-
}
|
|
71
|
-
let i = number;
|
|
72
|
-
while (i >= binary) {
|
|
73
|
-
i = i / binary;
|
|
74
|
-
index++;
|
|
75
|
-
}
|
|
76
|
-
if (!units[index]) {
|
|
77
|
-
index = units.length - 1;
|
|
78
|
-
}
|
|
79
|
-
return (number / Math.pow(binary, index)).toFixed(2) / 1 + units[index];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
67
|
export {
|
|
84
68
|
$,
|
|
85
69
|
dataType,
|
|
86
70
|
deepClone,
|
|
87
71
|
delayedTrigger,
|
|
88
|
-
getUnitNumber,
|
|
89
72
|
};
|