giser-maptalks-drawtool 1.0.0

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/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # giser-maptalks-drawtool
2
+
3
+ 基于 maptalks DrawTool 的扩展插件,添加绘制面时自相交检测功能。
4
+
5
+ ## 功能特性
6
+
7
+ - 绘制多边形时自动检测自相交
8
+ - 检测到自相交时自动回退到上一个点
9
+ - 阻止双击结束自相交的绘制
10
+ - 自定义错误提示消息和 UI
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ npm install giser-maptalks-drawtool
16
+ ```
17
+
18
+ ## 使用方式
19
+
20
+ ### 1. npm 引入(ES Module / CommonJS)
21
+
22
+ ```bash
23
+ npm install giser-maptalks-drawtool
24
+ ```
25
+
26
+ ```javascript
27
+ // ES Module
28
+ import { SelfIntersectionDrawTool } from 'giser-maptalks-drawtool';
29
+
30
+ // CommonJS
31
+ const { SelfIntersectionDrawTool } = require('giser-maptalks-drawtool');
32
+
33
+ // 使用
34
+ const drawTool = new SelfIntersectionDrawTool({
35
+ mode: 'polygon',
36
+ enableSelfIntersectionCheck: true,
37
+ selfIntersectionErrorMessage: '多边形不能自相交',
38
+ onSelfIntersectionError: function(message) {
39
+ alert(message);
40
+ }
41
+ }).addTo(map);
42
+ ```
43
+
44
+ ### 2. CDN script 标签引入
45
+
46
+ ```html
47
+ <script src="https://cdn.jsdelivr.net/npm/maptalks@1.0.0/dist/maptalks.min.js"></script>
48
+ <script src="https://cdn.jsdelivr.net/npm/giser-maptalks-drawtool/dist/giser-maptalks-drawtool.umd.js"></script>
49
+
50
+ <script>
51
+ const drawTool = new giserMaptalksDrawTool({
52
+ mode: 'polygon',
53
+ enableSelfIntersectionCheck: true,
54
+ selfIntersectionErrorMessage: '多边形不能自相交',
55
+ onSelfIntersectionError: function(message) {
56
+ alert(message);
57
+ }
58
+ }).addTo(map);
59
+ </script>
60
+ ```
61
+
62
+ ## 配置选项
63
+
64
+ | 选项 | 类型 | 默认值 | 说明 |
65
+ |------|------|--------|------|
66
+ | mode | string | null | 绘制模式:polygon, linestring, point 等 |
67
+ | enableSelfIntersectionCheck | boolean | false | 是否启用自相交检测 |
68
+ | selfIntersectionErrorMessage | string | '绘制面出现自相交,请重新绘制' | 自相交时的提示消息 |
69
+ | onSelfIntersectionError | function | null | 自相交时的回调函数,可用于自定义提示 UI |
70
+
71
+ 其他选项继承自 [maptalks DrawTool](http://maptalks.org/maptalks.js/api/classes/draw.DrawTool.html)。
72
+
73
+ ## 方法
74
+
75
+ | 方法 | 说明 |
76
+ |------|------|
77
+ | addTo(map) | 添加到地图 |
78
+ | setMode(mode) | 设置绘制模式 |
79
+ | getMode() | 获取当前模式 |
80
+ | enable() | 启用绘制工具 |
81
+ | disable() | 禁用绘制工具 |
82
+ | undo() | 回退到上一个点 |
83
+ | redo() | 重做 |
84
+ | on(event, handler) | 绑定事件 |
85
+ | off(event, handler) | 解绑事件 |
86
+ | getCurrentGeometry() | 获取当前正在绘制的几何图形 |
87
+ | getCurrentCoordinates() | 获取当前坐标数组 |
88
+ | isSelfIntersecting(coordinates) | 检测坐标是否自相交 |
89
+
90
+ ## 事件
91
+
92
+ | 事件 | 说明 |
93
+ |------|------|
94
+ | drawstart | 开始绘制 |
95
+ | drawvertex | 添加顶点 |
96
+ | drawend | 完成绘制 |
97
+ | selfintersectionwarning | 检测到自相交时触发 |
98
+
99
+ ## 示例
100
+
101
+ ### 基础用法
102
+
103
+ ```javascript
104
+ const drawTool = new SelfIntersectionDrawTool({
105
+ mode: 'polygon',
106
+ enableSelfIntersectionCheck: true
107
+ }).addTo(map);
108
+
109
+ drawTool.on('drawend', function(param) {
110
+ console.log('绘制完成', param.geometry);
111
+ });
112
+ ```
113
+
114
+ ### 自定义提示 UI
115
+
116
+ ```javascript
117
+ const drawTool = new SelfIntersectionDrawTool({
118
+ mode: 'polygon',
119
+ enableSelfIntersectionCheck: true,
120
+ selfIntersectionErrorMessage: '多边形不能自相交,请重新绘制',
121
+ onSelfIntersectionError: function(message) {
122
+ // 自定义提示样式
123
+ const toast = document.createElement('div');
124
+ toast.className = 'custom-toast';
125
+ toast.textContent = message;
126
+ document.body.appendChild(toast);
127
+ setTimeout(() => toast.remove(), 2500);
128
+ }
129
+ }).addTo(map);
130
+ ```
131
+
132
+ ### 监听警告事件
133
+
134
+ ```javascript
135
+ const drawTool = new SelfIntersectionDrawTool({
136
+ mode: 'polygon',
137
+ enableSelfIntersectionCheck: true
138
+ }).addTo(map);
139
+
140
+ drawTool.on('selfintersectionwarning', function(e) {
141
+ console.log('警告:', e.message);
142
+ });
143
+ ```
144
+
145
+ ## 完整示例 HTML
146
+
147
+ ```html
148
+ <!DOCTYPE html>
149
+ <html>
150
+ <head>
151
+ <meta charset="utf-8">
152
+ <title>giser-maptalks-drawtool 示例</title>
153
+ <script src="https://cdn.jsdelivr.net/npm/maptalks@1.0.0/dist/maptalks.min.js"></script>
154
+ <script src="https://cdn.jsdelivr.net/npm/giser-maptalks-drawtool/dist/giser-maptalks-drawtool.umd.js"></script>
155
+ <style>
156
+ #map { width: 100%; height: 100%; }
157
+ #message {
158
+ position: absolute;
159
+ top: 50%; left: 50%;
160
+ transform: translate(-50%, -50%);
161
+ background: rgba(220, 53, 69, 0.95);
162
+ color: white;
163
+ padding: 15px 30px;
164
+ border-radius: 6px;
165
+ display: none;
166
+ z-index: 2000;
167
+ }
168
+ </style>
169
+ </head>
170
+ <body>
171
+ <div id="map"></div>
172
+ <div id="message"></div>
173
+
174
+ <script>
175
+ const map = new maptalks.Map('map', {
176
+ center: [120.5, 31.3],
177
+ zoom: 10,
178
+ baseLayer: new maptalks.TileLayer('base', {
179
+ urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
180
+ })
181
+ });
182
+
183
+ const layer = new maptalks.VectorLayer('v').addTo(map);
184
+
185
+ const drawTool = new giserMaptalksDrawTool({
186
+ mode: 'polygon',
187
+ symbol: {
188
+ lineColor: '#4a8af4',
189
+ lineWidth: 2,
190
+ polygonFill: '#4a8af4'
191
+ },
192
+ enableSelfIntersectionCheck: true,
193
+ selfIntersectionErrorMessage: '多边形不能自相交,请重新绘制',
194
+ onSelfIntersectionError: function(message) {
195
+ const el = document.getElementById('message');
196
+ el.textContent = message;
197
+ el.style.display = 'block';
198
+ setTimeout(() => el.style.display = 'none', 2500);
199
+ }
200
+ }).addTo(map);
201
+
202
+ drawTool.on('drawend', function(param) {
203
+ if (param.geometry) {
204
+ layer.addGeometry(param.geometry);
205
+ }
206
+ });
207
+ </script>
208
+ </body>
209
+ </html>
210
+ ```
211
+
212
+ ## 目录结构
213
+
214
+ ```
215
+ ├── dist/
216
+ │ ├── giser-maptalks-drawtool.cjs.js # CommonJS
217
+ │ ├── giser-maptalks-drawtool.esm.js # ES Module
218
+ │ ├── giser-maptalks-drawtool.umd.js # UMD (script标签用)
219
+ │ └── index.d.ts # TypeScript 类型定义
220
+ ├── src/
221
+ │ └── index.ts # 源代码
222
+ ├── package.json
223
+ ├── rollup.config.js
224
+ └── tsconfig.json
225
+ ```
226
+
227
+ ## 本地构建
228
+
229
+ ```bash
230
+ # 安装依赖
231
+ npm install
232
+
233
+ # 构建
234
+ npm run build
235
+
236
+ # 监听模式
237
+ npm run dev
238
+ ```
@@ -0,0 +1,245 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ /* eslint-disable @typescript-eslint/no-explicit-any */
6
+ const DEFAULT_ERROR_MESSAGE = '绘制面出现自相交,请重新绘制';
7
+ const DBLCLICK_ERROR_MESSAGE = '绘制面存在自相交,请继续绘制';
8
+ const DRAWEND_ERROR_MESSAGE = '绘制面存在自相交,无法完成绘制,请继续绘制或按ESC取消';
9
+ /**
10
+ * 判断两条线段是否相交(跨立实验)
11
+ * ccw 函数提取到外层,避免每次调用重新创建
12
+ */
13
+ function ccw(A, B, C) {
14
+ return (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x);
15
+ }
16
+ function sharesEndpoint(p1, p2, p3, p4) {
17
+ return (p1.x === p3.x && p1.y === p3.y) ||
18
+ (p1.x === p4.x && p1.y === p4.y) ||
19
+ (p2.x === p3.x && p2.y === p3.y) ||
20
+ (p2.x === p4.x && p2.y === p4.y);
21
+ }
22
+ function segmentsIntersectSafe(p1, p2, p3, p4) {
23
+ if (sharesEndpoint(p1, p2, p3, p4))
24
+ return false;
25
+ return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);
26
+ }
27
+ /**
28
+ * 自定义 DrawTool,包装 maptalks DrawTool
29
+ * 添加功能:在绘制面过程中检测自相交,如果出现自相交则回退到上一个点
30
+ */
31
+ class SelfIntersectionDrawTool {
32
+ constructor(options) {
33
+ this._hasSelfIntersection = false;
34
+ const opts = Object.assign({}, { enableSelfIntersectionCheck: false }, options);
35
+ this._drawTool = new maptalks.DrawTool(opts);
36
+ this.options = this._drawTool.options;
37
+ this._selfIntersectionHandler = this._checkSelfIntersection.bind(this);
38
+ }
39
+ /**
40
+ * 触发警告
41
+ */
42
+ _fireWarning(message) {
43
+ var _a, _b;
44
+ this._drawTool._fireEvent('selfintersectionwarning', { type: 'selfintersectionwarning', message });
45
+ (_b = (_a = this.options).onSelfIntersectionError) === null || _b === void 0 ? void 0 : _b.call(_a, message);
46
+ }
47
+ /**
48
+ * 获取当前错误消息
49
+ */
50
+ _getErrorMessage(defaultMsg) {
51
+ return this.options.selfIntersectionErrorMessage || defaultMsg;
52
+ }
53
+ /**
54
+ * 从坐标中提取环
55
+ */
56
+ _getRing(coordinates) {
57
+ if (!coordinates || !Array.isArray(coordinates))
58
+ return null;
59
+ if (typeof coordinates[0].x === 'number') {
60
+ return coordinates;
61
+ }
62
+ if (Array.isArray(coordinates[0]) && Array.isArray(coordinates[0])) {
63
+ return coordinates[0];
64
+ }
65
+ return null;
66
+ }
67
+ /**
68
+ * 绑定自相交检测事件
69
+ */
70
+ _bindSelfIntersectionEvents() {
71
+ this._drawTool.off('drawvertex', this._selfIntersectionHandler);
72
+ if (!this.options.enableSelfIntersectionCheck)
73
+ return;
74
+ const mode = this.getMode();
75
+ if (mode === 'polygon' || mode === 'freeHandPolygon') {
76
+ this._drawTool.on('drawvertex', this._selfIntersectionHandler);
77
+ }
78
+ }
79
+ /**
80
+ * 绑定结束绘制拦截器
81
+ */
82
+ _bindEndDrawInterceptor() {
83
+ // 拦截双击
84
+ this._drawTool.on('dblclick', (param) => {
85
+ if (this._hasSelfIntersection) {
86
+ param.domEvent.stopPropagation();
87
+ param.domEvent.preventDefault();
88
+ this._fireWarning(this._getErrorMessage(DBLCLICK_ERROR_MESSAGE));
89
+ }
90
+ });
91
+ // 拦截绘制结束
92
+ this._drawTool.on('drawend', (param) => {
93
+ if (!param.geometry || !this._hasSelfIntersection)
94
+ return;
95
+ param.geometry.remove();
96
+ this._hasSelfIntersection = false;
97
+ this._fireWarning(this._getErrorMessage(DRAWEND_ERROR_MESSAGE));
98
+ });
99
+ }
100
+ // ========== DrawTool 方法的代理 ==========
101
+ addTo(map) {
102
+ this._drawTool.addTo(map);
103
+ this._bindSelfIntersectionEvents();
104
+ this._bindEndDrawInterceptor();
105
+ return this;
106
+ }
107
+ getMode() {
108
+ return this._drawTool.getMode();
109
+ }
110
+ setMode(mode) {
111
+ this._drawTool.setMode(mode);
112
+ this._hasSelfIntersection = false;
113
+ this._bindSelfIntersectionEvents();
114
+ return this;
115
+ }
116
+ getSymbol() {
117
+ return this._drawTool.getSymbol();
118
+ }
119
+ setSymbol(symbol) {
120
+ this._drawTool.setSymbol(symbol);
121
+ return this;
122
+ }
123
+ getCurrentGeometry() {
124
+ return this._drawTool.getCurrentGeometry();
125
+ }
126
+ undo() {
127
+ this._drawTool.undo();
128
+ return this;
129
+ }
130
+ redo() {
131
+ this._drawTool.redo();
132
+ return this;
133
+ }
134
+ endDraw(param) {
135
+ this._drawTool.endDraw(param);
136
+ return this;
137
+ }
138
+ on(eventType, handler) {
139
+ this._drawTool.on(eventType, handler);
140
+ return this;
141
+ }
142
+ off(eventType, handler) {
143
+ this._drawTool.off(eventType, handler);
144
+ return this;
145
+ }
146
+ enable() {
147
+ this._drawTool.enable();
148
+ return this;
149
+ }
150
+ disable() {
151
+ this._drawTool.disable();
152
+ return this;
153
+ }
154
+ isEnabled() {
155
+ return this._drawTool.isEnabled();
156
+ }
157
+ getMap() {
158
+ return this._drawTool.getMap();
159
+ }
160
+ addCoordinate(coordinate) {
161
+ this._drawTool.addCoordinate(coordinate);
162
+ return this;
163
+ }
164
+ getTempGeometry() {
165
+ return this._drawTool.getTempGeometry();
166
+ }
167
+ setLayerZIndex(zIndex) {
168
+ this._drawTool.setLayerZIndex(zIndex);
169
+ return this;
170
+ }
171
+ // ========== 自相交检测 ==========
172
+ getCurrentCoordinates() {
173
+ var _a;
174
+ return ((_a = this.getCurrentGeometry()) === null || _a === void 0 ? void 0 : _a.getCoordinates()) || null;
175
+ }
176
+ isSelfIntersecting(coordinates) {
177
+ if (!coordinates || coordinates.length === 0)
178
+ return false;
179
+ const ring = this._getRing(coordinates);
180
+ if (!ring || ring.length < 4)
181
+ return false;
182
+ const n = ring.length;
183
+ for (let i = 0; i < n; i++) {
184
+ const a1 = ring[i];
185
+ const a2 = ring[(i + 1) % n];
186
+ for (let j = 2; j < n; j++) {
187
+ if (Math.abs(i - j) <= 1)
188
+ continue;
189
+ if ((i === 0 && j === n - 1) || (j === 0 && i === n - 1))
190
+ continue;
191
+ if (segmentsIntersectSafe(a1, a2, ring[j], ring[(j + 1) % n])) {
192
+ return true;
193
+ }
194
+ }
195
+ }
196
+ return false;
197
+ }
198
+ /**
199
+ * 检测并处理自相交
200
+ */
201
+ _checkSelfIntersection() {
202
+ const coordinates = this.getCurrentCoordinates();
203
+ if (!coordinates)
204
+ return;
205
+ if (this.isSelfIntersecting(coordinates)) {
206
+ this._removeLastVertex();
207
+ this._hasSelfIntersection = true;
208
+ this._fireWarning(this._getErrorMessage(DEFAULT_ERROR_MESSAGE));
209
+ }
210
+ else {
211
+ this._hasSelfIntersection = false;
212
+ }
213
+ }
214
+ /**
215
+ * 移除最后一个顶点
216
+ */
217
+ _removeLastVertex() {
218
+ const geometry = this.getCurrentGeometry();
219
+ if (!geometry)
220
+ return;
221
+ const coords = geometry.getCoordinates();
222
+ if (!coords || coords.length === 0)
223
+ return;
224
+ const clickCoords = this._drawTool._clickCoords;
225
+ if (!clickCoords || clickCoords.length === 0)
226
+ return;
227
+ clickCoords.pop();
228
+ this._drawTool._historyPointer = clickCoords.length;
229
+ const ring = this._getRing(coords);
230
+ if (ring === null || ring === void 0 ? void 0 : ring.length) {
231
+ ring.pop();
232
+ geometry.setCoordinates(coords);
233
+ }
234
+ const registerMode = this._drawTool._getRegisterMode();
235
+ registerMode.update(this._drawTool.getMap().getProjection(), clickCoords, geometry);
236
+ }
237
+ }
238
+ // UMD 环境下暴露为 window.giserMaptalksDrawTool
239
+ if (typeof window !== 'undefined') {
240
+ window.giserMaptalksDrawTool = SelfIntersectionDrawTool;
241
+ }
242
+
243
+ exports.SelfIntersectionDrawTool = SelfIntersectionDrawTool;
244
+ exports["default"] = SelfIntersectionDrawTool;
245
+ //# sourceMappingURL=giser-maptalks-drawTool.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"giser-maptalks-drawTool.cjs.js","sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\n/**\r\n * 声明 maptalks 全局变量(UMD 模式下)\r\n */\r\ndeclare const maptalks: any;\r\n\r\n/**\r\n * 自定义 DrawTool 选项\r\n */\r\nexport interface SelfIntersectionDrawToolOptions {\r\n mode?: string;\r\n symbol?: any;\r\n once?: boolean;\r\n autoPanAtEdge?: boolean;\r\n blockGeometryEvents?: boolean;\r\n zIndex?: number;\r\n doubleClickZoom?: boolean;\r\n ignoreMouseleave?: boolean;\r\n enableAltitude?: boolean;\r\n interactive?: boolean;\r\n edgeAutoComplete?: boolean;\r\n transformCoordinate?: any;\r\n /** 是否启用自相交检测,默认 false */\r\n enableSelfIntersectionCheck?: boolean;\r\n /** 自相交时的提示消息 */\r\n selfIntersectionErrorMessage?: string;\r\n /** 自相交检测到时的回调函数 */\r\n onSelfIntersectionError?: (message: string) => void;\r\n [key: string]: any;\r\n}\r\n\r\nconst DEFAULT_ERROR_MESSAGE = '绘制面出现自相交,请重新绘制';\r\nconst DBLCLICK_ERROR_MESSAGE = '绘制面存在自相交,请继续绘制';\r\nconst DRAWEND_ERROR_MESSAGE = '绘制面存在自相交,无法完成绘制,请继续绘制或按ESC取消';\r\n\r\n/**\r\n * 判断两条线段是否相交(跨立实验)\r\n * ccw 函数提取到外层,避免每次调用重新创建\r\n */\r\nfunction ccw(A: any, B: any, C: any): boolean {\r\n return (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x);\r\n}\r\n\r\nfunction segmentsIntersect(p1: any, p2: any, p3: any, p4: any): boolean {\r\n return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);\r\n}\r\n\r\nfunction sharesEndpoint(p1: any, p2: any, p3: any, p4: any): boolean {\r\n return (p1.x === p3.x && p1.y === p3.y) ||\r\n (p1.x === p4.x && p1.y === p4.y) ||\r\n (p2.x === p3.x && p2.y === p3.y) ||\r\n (p2.x === p4.x && p2.y === p4.y);\r\n}\r\n\r\nfunction segmentsIntersectSafe(p1: any, p2: any, p3: any, p4: any): boolean {\r\n if (sharesEndpoint(p1, p2, p3, p4)) return false;\r\n return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);\r\n}\r\n\r\n/**\r\n * 自定义 DrawTool,包装 maptalks DrawTool\r\n * 添加功能:在绘制面过程中检测自相交,如果出现自相交则回退到上一个点\r\n */\r\nexport class SelfIntersectionDrawTool {\r\n\r\n private _drawTool: any;\r\n options: SelfIntersectionDrawToolOptions;\r\n private _selfIntersectionHandler: any;\r\n private _hasSelfIntersection: boolean = false;\r\n\r\n constructor(options: SelfIntersectionDrawToolOptions) {\r\n const opts = Object.assign({}, { enableSelfIntersectionCheck: false }, options);\r\n this._drawTool = new maptalks.DrawTool(opts);\r\n this.options = this._drawTool.options;\r\n this._selfIntersectionHandler = this._checkSelfIntersection.bind(this);\r\n }\r\n\r\n /**\r\n * 触发警告\r\n */\r\n private _fireWarning(message: string): void {\r\n this._drawTool._fireEvent('selfintersectionwarning', { type: 'selfintersectionwarning', message });\r\n this.options.onSelfIntersectionError?.(message);\r\n }\r\n\r\n /**\r\n * 获取当前错误消息\r\n */\r\n private _getErrorMessage(defaultMsg: string): string {\r\n return this.options.selfIntersectionErrorMessage || defaultMsg;\r\n }\r\n\r\n /**\r\n * 从坐标中提取环\r\n */\r\n private _getRing(coordinates: any[]): any[] | null {\r\n if (!coordinates || !Array.isArray(coordinates)) return null;\r\n\r\n if (typeof (coordinates[0] as any).x === 'number') {\r\n return coordinates;\r\n }\r\n\r\n if (Array.isArray(coordinates[0]) && Array.isArray(coordinates[0])) {\r\n return coordinates[0];\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 绑定自相交检测事件\r\n */\r\n private _bindSelfIntersectionEvents(): void {\r\n this._drawTool.off('drawvertex', this._selfIntersectionHandler);\r\n\r\n if (!this.options.enableSelfIntersectionCheck) return;\r\n\r\n const mode = this.getMode();\r\n if (mode === 'polygon' || mode === 'freeHandPolygon') {\r\n this._drawTool.on('drawvertex', this._selfIntersectionHandler);\r\n }\r\n }\r\n\r\n /**\r\n * 绑定结束绘制拦截器\r\n */\r\n private _bindEndDrawInterceptor(): void {\r\n // 拦截双击\r\n this._drawTool.on('dblclick', (param: any) => {\r\n if (this._hasSelfIntersection) {\r\n param.domEvent.stopPropagation();\r\n param.domEvent.preventDefault();\r\n this._fireWarning(this._getErrorMessage(DBLCLICK_ERROR_MESSAGE));\r\n }\r\n });\r\n\r\n // 拦截绘制结束\r\n this._drawTool.on('drawend', (param: any) => {\r\n if (!param.geometry || !this._hasSelfIntersection) return;\r\n\r\n param.geometry.remove();\r\n this._hasSelfIntersection = false;\r\n this._fireWarning(this._getErrorMessage(DRAWEND_ERROR_MESSAGE));\r\n });\r\n }\r\n\r\n // ========== DrawTool 方法的代理 ==========\r\n\r\n addTo(map: any): this {\r\n this._drawTool.addTo(map);\r\n this._bindSelfIntersectionEvents();\r\n this._bindEndDrawInterceptor();\r\n return this;\r\n }\r\n\r\n getMode(): string {\r\n return this._drawTool.getMode();\r\n }\r\n\r\n setMode(mode: string): this {\r\n this._drawTool.setMode(mode);\r\n this._hasSelfIntersection = false;\r\n this._bindSelfIntersectionEvents();\r\n return this;\r\n }\r\n\r\n getSymbol(): any {\r\n return this._drawTool.getSymbol();\r\n }\r\n\r\n setSymbol(symbol: any): this {\r\n this._drawTool.setSymbol(symbol);\r\n return this;\r\n }\r\n\r\n getCurrentGeometry(): any {\r\n return this._drawTool.getCurrentGeometry();\r\n }\r\n\r\n undo(): this {\r\n this._drawTool.undo();\r\n return this;\r\n }\r\n\r\n redo(): this {\r\n this._drawTool.redo();\r\n return this;\r\n }\r\n\r\n endDraw(param?: any): this {\r\n this._drawTool.endDraw(param);\r\n return this;\r\n }\r\n\r\n on(eventType: string, handler: any): this {\r\n this._drawTool.on(eventType, handler);\r\n return this;\r\n }\r\n\r\n off(eventType: string, handler: any): this {\r\n this._drawTool.off(eventType, handler);\r\n return this;\r\n }\r\n\r\n enable(): this {\r\n this._drawTool.enable();\r\n return this;\r\n }\r\n\r\n disable(): this {\r\n this._drawTool.disable();\r\n return this;\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this._drawTool.isEnabled();\r\n }\r\n\r\n getMap(): any {\r\n return this._drawTool.getMap();\r\n }\r\n\r\n addCoordinate(coordinate: any): this {\r\n this._drawTool.addCoordinate(coordinate);\r\n return this;\r\n }\r\n\r\n getTempGeometry(): any {\r\n return this._drawTool.getTempGeometry();\r\n }\r\n\r\n setLayerZIndex(zIndex: number): this {\r\n this._drawTool.setLayerZIndex(zIndex);\r\n return this;\r\n }\r\n\r\n // ========== 自相交检测 ==========\r\n\r\n getCurrentCoordinates(): any[] | null {\r\n return this.getCurrentGeometry()?.getCoordinates() || null;\r\n }\r\n\r\n isSelfIntersecting(coordinates: any[]): boolean {\r\n if (!coordinates || coordinates.length === 0) return false;\r\n\r\n const ring = this._getRing(coordinates);\r\n if (!ring || ring.length < 4) return false;\r\n\r\n const n = ring.length;\r\n for (let i = 0; i < n; i++) {\r\n const a1 = ring[i];\r\n const a2 = ring[(i + 1) % n];\r\n\r\n for (let j = 2; j < n; j++) {\r\n if (Math.abs(i - j) <= 1) continue;\r\n if ((i === 0 && j === n - 1) || (j === 0 && i === n - 1)) continue;\r\n\r\n if (segmentsIntersectSafe(a1, a2, ring[j], ring[(j + 1) % n])) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * 检测并处理自相交\r\n */\r\n private _checkSelfIntersection(): void {\r\n const coordinates = this.getCurrentCoordinates();\r\n if (!coordinates) return;\r\n\r\n if (this.isSelfIntersecting(coordinates)) {\r\n this._removeLastVertex();\r\n this._hasSelfIntersection = true;\r\n this._fireWarning(this._getErrorMessage(DEFAULT_ERROR_MESSAGE));\r\n } else {\r\n this._hasSelfIntersection = false;\r\n }\r\n }\r\n\r\n /**\r\n * 移除最后一个顶点\r\n */\r\n private _removeLastVertex(): void {\r\n const geometry = this.getCurrentGeometry();\r\n if (!geometry) return;\r\n\r\n const coords = geometry.getCoordinates();\r\n if (!coords || coords.length === 0) return;\r\n\r\n const clickCoords = this._drawTool._clickCoords;\r\n if (!clickCoords || clickCoords.length === 0) return;\r\n\r\n clickCoords.pop();\r\n this._drawTool._historyPointer = clickCoords.length;\r\n\r\n const ring = this._getRing(coords);\r\n if (ring?.length) {\r\n ring.pop();\r\n geometry.setCoordinates(coords);\r\n }\r\n\r\n const registerMode = this._drawTool._getRegisterMode();\r\n registerMode.update(this._drawTool.getMap().getProjection(), clickCoords, geometry);\r\n }\r\n}\r\n\r\n// UMD 环境下暴露为 window.giserMaptalksDrawTool\r\nif (typeof window !== 'undefined') {\r\n (window as any).giserMaptalksDrawTool = SelfIntersectionDrawTool;\r\n}\r\n\r\nexport default SelfIntersectionDrawTool;"],"names":[],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ const DEFAULT_ERROR_MESSAGE = '绘制面出现自相交,请重新绘制';
3
+ const DBLCLICK_ERROR_MESSAGE = '绘制面存在自相交,请继续绘制';
4
+ const DRAWEND_ERROR_MESSAGE = '绘制面存在自相交,无法完成绘制,请继续绘制或按ESC取消';
5
+ /**
6
+ * 判断两条线段是否相交(跨立实验)
7
+ * ccw 函数提取到外层,避免每次调用重新创建
8
+ */
9
+ function ccw(A, B, C) {
10
+ return (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x);
11
+ }
12
+ function sharesEndpoint(p1, p2, p3, p4) {
13
+ return (p1.x === p3.x && p1.y === p3.y) ||
14
+ (p1.x === p4.x && p1.y === p4.y) ||
15
+ (p2.x === p3.x && p2.y === p3.y) ||
16
+ (p2.x === p4.x && p2.y === p4.y);
17
+ }
18
+ function segmentsIntersectSafe(p1, p2, p3, p4) {
19
+ if (sharesEndpoint(p1, p2, p3, p4))
20
+ return false;
21
+ return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);
22
+ }
23
+ /**
24
+ * 自定义 DrawTool,包装 maptalks DrawTool
25
+ * 添加功能:在绘制面过程中检测自相交,如果出现自相交则回退到上一个点
26
+ */
27
+ class SelfIntersectionDrawTool {
28
+ constructor(options) {
29
+ this._hasSelfIntersection = false;
30
+ const opts = Object.assign({}, { enableSelfIntersectionCheck: false }, options);
31
+ this._drawTool = new maptalks.DrawTool(opts);
32
+ this.options = this._drawTool.options;
33
+ this._selfIntersectionHandler = this._checkSelfIntersection.bind(this);
34
+ }
35
+ /**
36
+ * 触发警告
37
+ */
38
+ _fireWarning(message) {
39
+ var _a, _b;
40
+ this._drawTool._fireEvent('selfintersectionwarning', { type: 'selfintersectionwarning', message });
41
+ (_b = (_a = this.options).onSelfIntersectionError) === null || _b === void 0 ? void 0 : _b.call(_a, message);
42
+ }
43
+ /**
44
+ * 获取当前错误消息
45
+ */
46
+ _getErrorMessage(defaultMsg) {
47
+ return this.options.selfIntersectionErrorMessage || defaultMsg;
48
+ }
49
+ /**
50
+ * 从坐标中提取环
51
+ */
52
+ _getRing(coordinates) {
53
+ if (!coordinates || !Array.isArray(coordinates))
54
+ return null;
55
+ if (typeof coordinates[0].x === 'number') {
56
+ return coordinates;
57
+ }
58
+ if (Array.isArray(coordinates[0]) && Array.isArray(coordinates[0])) {
59
+ return coordinates[0];
60
+ }
61
+ return null;
62
+ }
63
+ /**
64
+ * 绑定自相交检测事件
65
+ */
66
+ _bindSelfIntersectionEvents() {
67
+ this._drawTool.off('drawvertex', this._selfIntersectionHandler);
68
+ if (!this.options.enableSelfIntersectionCheck)
69
+ return;
70
+ const mode = this.getMode();
71
+ if (mode === 'polygon' || mode === 'freeHandPolygon') {
72
+ this._drawTool.on('drawvertex', this._selfIntersectionHandler);
73
+ }
74
+ }
75
+ /**
76
+ * 绑定结束绘制拦截器
77
+ */
78
+ _bindEndDrawInterceptor() {
79
+ // 拦截双击
80
+ this._drawTool.on('dblclick', (param) => {
81
+ if (this._hasSelfIntersection) {
82
+ param.domEvent.stopPropagation();
83
+ param.domEvent.preventDefault();
84
+ this._fireWarning(this._getErrorMessage(DBLCLICK_ERROR_MESSAGE));
85
+ }
86
+ });
87
+ // 拦截绘制结束
88
+ this._drawTool.on('drawend', (param) => {
89
+ if (!param.geometry || !this._hasSelfIntersection)
90
+ return;
91
+ param.geometry.remove();
92
+ this._hasSelfIntersection = false;
93
+ this._fireWarning(this._getErrorMessage(DRAWEND_ERROR_MESSAGE));
94
+ });
95
+ }
96
+ // ========== DrawTool 方法的代理 ==========
97
+ addTo(map) {
98
+ this._drawTool.addTo(map);
99
+ this._bindSelfIntersectionEvents();
100
+ this._bindEndDrawInterceptor();
101
+ return this;
102
+ }
103
+ getMode() {
104
+ return this._drawTool.getMode();
105
+ }
106
+ setMode(mode) {
107
+ this._drawTool.setMode(mode);
108
+ this._hasSelfIntersection = false;
109
+ this._bindSelfIntersectionEvents();
110
+ return this;
111
+ }
112
+ getSymbol() {
113
+ return this._drawTool.getSymbol();
114
+ }
115
+ setSymbol(symbol) {
116
+ this._drawTool.setSymbol(symbol);
117
+ return this;
118
+ }
119
+ getCurrentGeometry() {
120
+ return this._drawTool.getCurrentGeometry();
121
+ }
122
+ undo() {
123
+ this._drawTool.undo();
124
+ return this;
125
+ }
126
+ redo() {
127
+ this._drawTool.redo();
128
+ return this;
129
+ }
130
+ endDraw(param) {
131
+ this._drawTool.endDraw(param);
132
+ return this;
133
+ }
134
+ on(eventType, handler) {
135
+ this._drawTool.on(eventType, handler);
136
+ return this;
137
+ }
138
+ off(eventType, handler) {
139
+ this._drawTool.off(eventType, handler);
140
+ return this;
141
+ }
142
+ enable() {
143
+ this._drawTool.enable();
144
+ return this;
145
+ }
146
+ disable() {
147
+ this._drawTool.disable();
148
+ return this;
149
+ }
150
+ isEnabled() {
151
+ return this._drawTool.isEnabled();
152
+ }
153
+ getMap() {
154
+ return this._drawTool.getMap();
155
+ }
156
+ addCoordinate(coordinate) {
157
+ this._drawTool.addCoordinate(coordinate);
158
+ return this;
159
+ }
160
+ getTempGeometry() {
161
+ return this._drawTool.getTempGeometry();
162
+ }
163
+ setLayerZIndex(zIndex) {
164
+ this._drawTool.setLayerZIndex(zIndex);
165
+ return this;
166
+ }
167
+ // ========== 自相交检测 ==========
168
+ getCurrentCoordinates() {
169
+ var _a;
170
+ return ((_a = this.getCurrentGeometry()) === null || _a === void 0 ? void 0 : _a.getCoordinates()) || null;
171
+ }
172
+ isSelfIntersecting(coordinates) {
173
+ if (!coordinates || coordinates.length === 0)
174
+ return false;
175
+ const ring = this._getRing(coordinates);
176
+ if (!ring || ring.length < 4)
177
+ return false;
178
+ const n = ring.length;
179
+ for (let i = 0; i < n; i++) {
180
+ const a1 = ring[i];
181
+ const a2 = ring[(i + 1) % n];
182
+ for (let j = 2; j < n; j++) {
183
+ if (Math.abs(i - j) <= 1)
184
+ continue;
185
+ if ((i === 0 && j === n - 1) || (j === 0 && i === n - 1))
186
+ continue;
187
+ if (segmentsIntersectSafe(a1, a2, ring[j], ring[(j + 1) % n])) {
188
+ return true;
189
+ }
190
+ }
191
+ }
192
+ return false;
193
+ }
194
+ /**
195
+ * 检测并处理自相交
196
+ */
197
+ _checkSelfIntersection() {
198
+ const coordinates = this.getCurrentCoordinates();
199
+ if (!coordinates)
200
+ return;
201
+ if (this.isSelfIntersecting(coordinates)) {
202
+ this._removeLastVertex();
203
+ this._hasSelfIntersection = true;
204
+ this._fireWarning(this._getErrorMessage(DEFAULT_ERROR_MESSAGE));
205
+ }
206
+ else {
207
+ this._hasSelfIntersection = false;
208
+ }
209
+ }
210
+ /**
211
+ * 移除最后一个顶点
212
+ */
213
+ _removeLastVertex() {
214
+ const geometry = this.getCurrentGeometry();
215
+ if (!geometry)
216
+ return;
217
+ const coords = geometry.getCoordinates();
218
+ if (!coords || coords.length === 0)
219
+ return;
220
+ const clickCoords = this._drawTool._clickCoords;
221
+ if (!clickCoords || clickCoords.length === 0)
222
+ return;
223
+ clickCoords.pop();
224
+ this._drawTool._historyPointer = clickCoords.length;
225
+ const ring = this._getRing(coords);
226
+ if (ring === null || ring === void 0 ? void 0 : ring.length) {
227
+ ring.pop();
228
+ geometry.setCoordinates(coords);
229
+ }
230
+ const registerMode = this._drawTool._getRegisterMode();
231
+ registerMode.update(this._drawTool.getMap().getProjection(), clickCoords, geometry);
232
+ }
233
+ }
234
+ // UMD 环境下暴露为 window.giserMaptalksDrawTool
235
+ if (typeof window !== 'undefined') {
236
+ window.giserMaptalksDrawTool = SelfIntersectionDrawTool;
237
+ }
238
+
239
+ export { SelfIntersectionDrawTool, SelfIntersectionDrawTool as default };
240
+ //# sourceMappingURL=giser-maptalks-drawTool.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"giser-maptalks-drawTool.esm.js","sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\n/**\r\n * 声明 maptalks 全局变量(UMD 模式下)\r\n */\r\ndeclare const maptalks: any;\r\n\r\n/**\r\n * 自定义 DrawTool 选项\r\n */\r\nexport interface SelfIntersectionDrawToolOptions {\r\n mode?: string;\r\n symbol?: any;\r\n once?: boolean;\r\n autoPanAtEdge?: boolean;\r\n blockGeometryEvents?: boolean;\r\n zIndex?: number;\r\n doubleClickZoom?: boolean;\r\n ignoreMouseleave?: boolean;\r\n enableAltitude?: boolean;\r\n interactive?: boolean;\r\n edgeAutoComplete?: boolean;\r\n transformCoordinate?: any;\r\n /** 是否启用自相交检测,默认 false */\r\n enableSelfIntersectionCheck?: boolean;\r\n /** 自相交时的提示消息 */\r\n selfIntersectionErrorMessage?: string;\r\n /** 自相交检测到时的回调函数 */\r\n onSelfIntersectionError?: (message: string) => void;\r\n [key: string]: any;\r\n}\r\n\r\nconst DEFAULT_ERROR_MESSAGE = '绘制面出现自相交,请重新绘制';\r\nconst DBLCLICK_ERROR_MESSAGE = '绘制面存在自相交,请继续绘制';\r\nconst DRAWEND_ERROR_MESSAGE = '绘制面存在自相交,无法完成绘制,请继续绘制或按ESC取消';\r\n\r\n/**\r\n * 判断两条线段是否相交(跨立实验)\r\n * ccw 函数提取到外层,避免每次调用重新创建\r\n */\r\nfunction ccw(A: any, B: any, C: any): boolean {\r\n return (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x);\r\n}\r\n\r\nfunction segmentsIntersect(p1: any, p2: any, p3: any, p4: any): boolean {\r\n return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);\r\n}\r\n\r\nfunction sharesEndpoint(p1: any, p2: any, p3: any, p4: any): boolean {\r\n return (p1.x === p3.x && p1.y === p3.y) ||\r\n (p1.x === p4.x && p1.y === p4.y) ||\r\n (p2.x === p3.x && p2.y === p3.y) ||\r\n (p2.x === p4.x && p2.y === p4.y);\r\n}\r\n\r\nfunction segmentsIntersectSafe(p1: any, p2: any, p3: any, p4: any): boolean {\r\n if (sharesEndpoint(p1, p2, p3, p4)) return false;\r\n return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);\r\n}\r\n\r\n/**\r\n * 自定义 DrawTool,包装 maptalks DrawTool\r\n * 添加功能:在绘制面过程中检测自相交,如果出现自相交则回退到上一个点\r\n */\r\nexport class SelfIntersectionDrawTool {\r\n\r\n private _drawTool: any;\r\n options: SelfIntersectionDrawToolOptions;\r\n private _selfIntersectionHandler: any;\r\n private _hasSelfIntersection: boolean = false;\r\n\r\n constructor(options: SelfIntersectionDrawToolOptions) {\r\n const opts = Object.assign({}, { enableSelfIntersectionCheck: false }, options);\r\n this._drawTool = new maptalks.DrawTool(opts);\r\n this.options = this._drawTool.options;\r\n this._selfIntersectionHandler = this._checkSelfIntersection.bind(this);\r\n }\r\n\r\n /**\r\n * 触发警告\r\n */\r\n private _fireWarning(message: string): void {\r\n this._drawTool._fireEvent('selfintersectionwarning', { type: 'selfintersectionwarning', message });\r\n this.options.onSelfIntersectionError?.(message);\r\n }\r\n\r\n /**\r\n * 获取当前错误消息\r\n */\r\n private _getErrorMessage(defaultMsg: string): string {\r\n return this.options.selfIntersectionErrorMessage || defaultMsg;\r\n }\r\n\r\n /**\r\n * 从坐标中提取环\r\n */\r\n private _getRing(coordinates: any[]): any[] | null {\r\n if (!coordinates || !Array.isArray(coordinates)) return null;\r\n\r\n if (typeof (coordinates[0] as any).x === 'number') {\r\n return coordinates;\r\n }\r\n\r\n if (Array.isArray(coordinates[0]) && Array.isArray(coordinates[0])) {\r\n return coordinates[0];\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 绑定自相交检测事件\r\n */\r\n private _bindSelfIntersectionEvents(): void {\r\n this._drawTool.off('drawvertex', this._selfIntersectionHandler);\r\n\r\n if (!this.options.enableSelfIntersectionCheck) return;\r\n\r\n const mode = this.getMode();\r\n if (mode === 'polygon' || mode === 'freeHandPolygon') {\r\n this._drawTool.on('drawvertex', this._selfIntersectionHandler);\r\n }\r\n }\r\n\r\n /**\r\n * 绑定结束绘制拦截器\r\n */\r\n private _bindEndDrawInterceptor(): void {\r\n // 拦截双击\r\n this._drawTool.on('dblclick', (param: any) => {\r\n if (this._hasSelfIntersection) {\r\n param.domEvent.stopPropagation();\r\n param.domEvent.preventDefault();\r\n this._fireWarning(this._getErrorMessage(DBLCLICK_ERROR_MESSAGE));\r\n }\r\n });\r\n\r\n // 拦截绘制结束\r\n this._drawTool.on('drawend', (param: any) => {\r\n if (!param.geometry || !this._hasSelfIntersection) return;\r\n\r\n param.geometry.remove();\r\n this._hasSelfIntersection = false;\r\n this._fireWarning(this._getErrorMessage(DRAWEND_ERROR_MESSAGE));\r\n });\r\n }\r\n\r\n // ========== DrawTool 方法的代理 ==========\r\n\r\n addTo(map: any): this {\r\n this._drawTool.addTo(map);\r\n this._bindSelfIntersectionEvents();\r\n this._bindEndDrawInterceptor();\r\n return this;\r\n }\r\n\r\n getMode(): string {\r\n return this._drawTool.getMode();\r\n }\r\n\r\n setMode(mode: string): this {\r\n this._drawTool.setMode(mode);\r\n this._hasSelfIntersection = false;\r\n this._bindSelfIntersectionEvents();\r\n return this;\r\n }\r\n\r\n getSymbol(): any {\r\n return this._drawTool.getSymbol();\r\n }\r\n\r\n setSymbol(symbol: any): this {\r\n this._drawTool.setSymbol(symbol);\r\n return this;\r\n }\r\n\r\n getCurrentGeometry(): any {\r\n return this._drawTool.getCurrentGeometry();\r\n }\r\n\r\n undo(): this {\r\n this._drawTool.undo();\r\n return this;\r\n }\r\n\r\n redo(): this {\r\n this._drawTool.redo();\r\n return this;\r\n }\r\n\r\n endDraw(param?: any): this {\r\n this._drawTool.endDraw(param);\r\n return this;\r\n }\r\n\r\n on(eventType: string, handler: any): this {\r\n this._drawTool.on(eventType, handler);\r\n return this;\r\n }\r\n\r\n off(eventType: string, handler: any): this {\r\n this._drawTool.off(eventType, handler);\r\n return this;\r\n }\r\n\r\n enable(): this {\r\n this._drawTool.enable();\r\n return this;\r\n }\r\n\r\n disable(): this {\r\n this._drawTool.disable();\r\n return this;\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this._drawTool.isEnabled();\r\n }\r\n\r\n getMap(): any {\r\n return this._drawTool.getMap();\r\n }\r\n\r\n addCoordinate(coordinate: any): this {\r\n this._drawTool.addCoordinate(coordinate);\r\n return this;\r\n }\r\n\r\n getTempGeometry(): any {\r\n return this._drawTool.getTempGeometry();\r\n }\r\n\r\n setLayerZIndex(zIndex: number): this {\r\n this._drawTool.setLayerZIndex(zIndex);\r\n return this;\r\n }\r\n\r\n // ========== 自相交检测 ==========\r\n\r\n getCurrentCoordinates(): any[] | null {\r\n return this.getCurrentGeometry()?.getCoordinates() || null;\r\n }\r\n\r\n isSelfIntersecting(coordinates: any[]): boolean {\r\n if (!coordinates || coordinates.length === 0) return false;\r\n\r\n const ring = this._getRing(coordinates);\r\n if (!ring || ring.length < 4) return false;\r\n\r\n const n = ring.length;\r\n for (let i = 0; i < n; i++) {\r\n const a1 = ring[i];\r\n const a2 = ring[(i + 1) % n];\r\n\r\n for (let j = 2; j < n; j++) {\r\n if (Math.abs(i - j) <= 1) continue;\r\n if ((i === 0 && j === n - 1) || (j === 0 && i === n - 1)) continue;\r\n\r\n if (segmentsIntersectSafe(a1, a2, ring[j], ring[(j + 1) % n])) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * 检测并处理自相交\r\n */\r\n private _checkSelfIntersection(): void {\r\n const coordinates = this.getCurrentCoordinates();\r\n if (!coordinates) return;\r\n\r\n if (this.isSelfIntersecting(coordinates)) {\r\n this._removeLastVertex();\r\n this._hasSelfIntersection = true;\r\n this._fireWarning(this._getErrorMessage(DEFAULT_ERROR_MESSAGE));\r\n } else {\r\n this._hasSelfIntersection = false;\r\n }\r\n }\r\n\r\n /**\r\n * 移除最后一个顶点\r\n */\r\n private _removeLastVertex(): void {\r\n const geometry = this.getCurrentGeometry();\r\n if (!geometry) return;\r\n\r\n const coords = geometry.getCoordinates();\r\n if (!coords || coords.length === 0) return;\r\n\r\n const clickCoords = this._drawTool._clickCoords;\r\n if (!clickCoords || clickCoords.length === 0) return;\r\n\r\n clickCoords.pop();\r\n this._drawTool._historyPointer = clickCoords.length;\r\n\r\n const ring = this._getRing(coords);\r\n if (ring?.length) {\r\n ring.pop();\r\n geometry.setCoordinates(coords);\r\n }\r\n\r\n const registerMode = this._drawTool._getRegisterMode();\r\n registerMode.update(this._drawTool.getMap().getProjection(), clickCoords, geometry);\r\n }\r\n}\r\n\r\n// UMD 环境下暴露为 window.giserMaptalksDrawTool\r\nif (typeof window !== 'undefined') {\r\n (window as any).giserMaptalksDrawTool = SelfIntersectionDrawTool;\r\n}\r\n\r\nexport default SelfIntersectionDrawTool;"],"names":[],"mappings":"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"}
@@ -0,0 +1,251 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.giserMaptalksDrawTool = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
+ const DEFAULT_ERROR_MESSAGE = '绘制面出现自相交,请重新绘制';
9
+ const DBLCLICK_ERROR_MESSAGE = '绘制面存在自相交,请继续绘制';
10
+ const DRAWEND_ERROR_MESSAGE = '绘制面存在自相交,无法完成绘制,请继续绘制或按ESC取消';
11
+ /**
12
+ * 判断两条线段是否相交(跨立实验)
13
+ * ccw 函数提取到外层,避免每次调用重新创建
14
+ */
15
+ function ccw(A, B, C) {
16
+ return (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x);
17
+ }
18
+ function sharesEndpoint(p1, p2, p3, p4) {
19
+ return (p1.x === p3.x && p1.y === p3.y) ||
20
+ (p1.x === p4.x && p1.y === p4.y) ||
21
+ (p2.x === p3.x && p2.y === p3.y) ||
22
+ (p2.x === p4.x && p2.y === p4.y);
23
+ }
24
+ function segmentsIntersectSafe(p1, p2, p3, p4) {
25
+ if (sharesEndpoint(p1, p2, p3, p4))
26
+ return false;
27
+ return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);
28
+ }
29
+ /**
30
+ * 自定义 DrawTool,包装 maptalks DrawTool
31
+ * 添加功能:在绘制面过程中检测自相交,如果出现自相交则回退到上一个点
32
+ */
33
+ class SelfIntersectionDrawTool {
34
+ constructor(options) {
35
+ this._hasSelfIntersection = false;
36
+ const opts = Object.assign({}, { enableSelfIntersectionCheck: false }, options);
37
+ this._drawTool = new maptalks.DrawTool(opts);
38
+ this.options = this._drawTool.options;
39
+ this._selfIntersectionHandler = this._checkSelfIntersection.bind(this);
40
+ }
41
+ /**
42
+ * 触发警告
43
+ */
44
+ _fireWarning(message) {
45
+ var _a, _b;
46
+ this._drawTool._fireEvent('selfintersectionwarning', { type: 'selfintersectionwarning', message });
47
+ (_b = (_a = this.options).onSelfIntersectionError) === null || _b === void 0 ? void 0 : _b.call(_a, message);
48
+ }
49
+ /**
50
+ * 获取当前错误消息
51
+ */
52
+ _getErrorMessage(defaultMsg) {
53
+ return this.options.selfIntersectionErrorMessage || defaultMsg;
54
+ }
55
+ /**
56
+ * 从坐标中提取环
57
+ */
58
+ _getRing(coordinates) {
59
+ if (!coordinates || !Array.isArray(coordinates))
60
+ return null;
61
+ if (typeof coordinates[0].x === 'number') {
62
+ return coordinates;
63
+ }
64
+ if (Array.isArray(coordinates[0]) && Array.isArray(coordinates[0])) {
65
+ return coordinates[0];
66
+ }
67
+ return null;
68
+ }
69
+ /**
70
+ * 绑定自相交检测事件
71
+ */
72
+ _bindSelfIntersectionEvents() {
73
+ this._drawTool.off('drawvertex', this._selfIntersectionHandler);
74
+ if (!this.options.enableSelfIntersectionCheck)
75
+ return;
76
+ const mode = this.getMode();
77
+ if (mode === 'polygon' || mode === 'freeHandPolygon') {
78
+ this._drawTool.on('drawvertex', this._selfIntersectionHandler);
79
+ }
80
+ }
81
+ /**
82
+ * 绑定结束绘制拦截器
83
+ */
84
+ _bindEndDrawInterceptor() {
85
+ // 拦截双击
86
+ this._drawTool.on('dblclick', (param) => {
87
+ if (this._hasSelfIntersection) {
88
+ param.domEvent.stopPropagation();
89
+ param.domEvent.preventDefault();
90
+ this._fireWarning(this._getErrorMessage(DBLCLICK_ERROR_MESSAGE));
91
+ }
92
+ });
93
+ // 拦截绘制结束
94
+ this._drawTool.on('drawend', (param) => {
95
+ if (!param.geometry || !this._hasSelfIntersection)
96
+ return;
97
+ param.geometry.remove();
98
+ this._hasSelfIntersection = false;
99
+ this._fireWarning(this._getErrorMessage(DRAWEND_ERROR_MESSAGE));
100
+ });
101
+ }
102
+ // ========== DrawTool 方法的代理 ==========
103
+ addTo(map) {
104
+ this._drawTool.addTo(map);
105
+ this._bindSelfIntersectionEvents();
106
+ this._bindEndDrawInterceptor();
107
+ return this;
108
+ }
109
+ getMode() {
110
+ return this._drawTool.getMode();
111
+ }
112
+ setMode(mode) {
113
+ this._drawTool.setMode(mode);
114
+ this._hasSelfIntersection = false;
115
+ this._bindSelfIntersectionEvents();
116
+ return this;
117
+ }
118
+ getSymbol() {
119
+ return this._drawTool.getSymbol();
120
+ }
121
+ setSymbol(symbol) {
122
+ this._drawTool.setSymbol(symbol);
123
+ return this;
124
+ }
125
+ getCurrentGeometry() {
126
+ return this._drawTool.getCurrentGeometry();
127
+ }
128
+ undo() {
129
+ this._drawTool.undo();
130
+ return this;
131
+ }
132
+ redo() {
133
+ this._drawTool.redo();
134
+ return this;
135
+ }
136
+ endDraw(param) {
137
+ this._drawTool.endDraw(param);
138
+ return this;
139
+ }
140
+ on(eventType, handler) {
141
+ this._drawTool.on(eventType, handler);
142
+ return this;
143
+ }
144
+ off(eventType, handler) {
145
+ this._drawTool.off(eventType, handler);
146
+ return this;
147
+ }
148
+ enable() {
149
+ this._drawTool.enable();
150
+ return this;
151
+ }
152
+ disable() {
153
+ this._drawTool.disable();
154
+ return this;
155
+ }
156
+ isEnabled() {
157
+ return this._drawTool.isEnabled();
158
+ }
159
+ getMap() {
160
+ return this._drawTool.getMap();
161
+ }
162
+ addCoordinate(coordinate) {
163
+ this._drawTool.addCoordinate(coordinate);
164
+ return this;
165
+ }
166
+ getTempGeometry() {
167
+ return this._drawTool.getTempGeometry();
168
+ }
169
+ setLayerZIndex(zIndex) {
170
+ this._drawTool.setLayerZIndex(zIndex);
171
+ return this;
172
+ }
173
+ // ========== 自相交检测 ==========
174
+ getCurrentCoordinates() {
175
+ var _a;
176
+ return ((_a = this.getCurrentGeometry()) === null || _a === void 0 ? void 0 : _a.getCoordinates()) || null;
177
+ }
178
+ isSelfIntersecting(coordinates) {
179
+ if (!coordinates || coordinates.length === 0)
180
+ return false;
181
+ const ring = this._getRing(coordinates);
182
+ if (!ring || ring.length < 4)
183
+ return false;
184
+ const n = ring.length;
185
+ for (let i = 0; i < n; i++) {
186
+ const a1 = ring[i];
187
+ const a2 = ring[(i + 1) % n];
188
+ for (let j = 2; j < n; j++) {
189
+ if (Math.abs(i - j) <= 1)
190
+ continue;
191
+ if ((i === 0 && j === n - 1) || (j === 0 && i === n - 1))
192
+ continue;
193
+ if (segmentsIntersectSafe(a1, a2, ring[j], ring[(j + 1) % n])) {
194
+ return true;
195
+ }
196
+ }
197
+ }
198
+ return false;
199
+ }
200
+ /**
201
+ * 检测并处理自相交
202
+ */
203
+ _checkSelfIntersection() {
204
+ const coordinates = this.getCurrentCoordinates();
205
+ if (!coordinates)
206
+ return;
207
+ if (this.isSelfIntersecting(coordinates)) {
208
+ this._removeLastVertex();
209
+ this._hasSelfIntersection = true;
210
+ this._fireWarning(this._getErrorMessage(DEFAULT_ERROR_MESSAGE));
211
+ }
212
+ else {
213
+ this._hasSelfIntersection = false;
214
+ }
215
+ }
216
+ /**
217
+ * 移除最后一个顶点
218
+ */
219
+ _removeLastVertex() {
220
+ const geometry = this.getCurrentGeometry();
221
+ if (!geometry)
222
+ return;
223
+ const coords = geometry.getCoordinates();
224
+ if (!coords || coords.length === 0)
225
+ return;
226
+ const clickCoords = this._drawTool._clickCoords;
227
+ if (!clickCoords || clickCoords.length === 0)
228
+ return;
229
+ clickCoords.pop();
230
+ this._drawTool._historyPointer = clickCoords.length;
231
+ const ring = this._getRing(coords);
232
+ if (ring === null || ring === void 0 ? void 0 : ring.length) {
233
+ ring.pop();
234
+ geometry.setCoordinates(coords);
235
+ }
236
+ const registerMode = this._drawTool._getRegisterMode();
237
+ registerMode.update(this._drawTool.getMap().getProjection(), clickCoords, geometry);
238
+ }
239
+ }
240
+ // UMD 环境下暴露为 window.giserMaptalksDrawTool
241
+ if (typeof window !== 'undefined') {
242
+ window.giserMaptalksDrawTool = SelfIntersectionDrawTool;
243
+ }
244
+
245
+ exports.SelfIntersectionDrawTool = SelfIntersectionDrawTool;
246
+ exports["default"] = SelfIntersectionDrawTool;
247
+
248
+ Object.defineProperty(exports, '__esModule', { value: true });
249
+
250
+ }));
251
+ //# sourceMappingURL=giser-maptalks-drawTool.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"giser-maptalks-drawTool.umd.js","sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\n/**\r\n * 声明 maptalks 全局变量(UMD 模式下)\r\n */\r\ndeclare const maptalks: any;\r\n\r\n/**\r\n * 自定义 DrawTool 选项\r\n */\r\nexport interface SelfIntersectionDrawToolOptions {\r\n mode?: string;\r\n symbol?: any;\r\n once?: boolean;\r\n autoPanAtEdge?: boolean;\r\n blockGeometryEvents?: boolean;\r\n zIndex?: number;\r\n doubleClickZoom?: boolean;\r\n ignoreMouseleave?: boolean;\r\n enableAltitude?: boolean;\r\n interactive?: boolean;\r\n edgeAutoComplete?: boolean;\r\n transformCoordinate?: any;\r\n /** 是否启用自相交检测,默认 false */\r\n enableSelfIntersectionCheck?: boolean;\r\n /** 自相交时的提示消息 */\r\n selfIntersectionErrorMessage?: string;\r\n /** 自相交检测到时的回调函数 */\r\n onSelfIntersectionError?: (message: string) => void;\r\n [key: string]: any;\r\n}\r\n\r\nconst DEFAULT_ERROR_MESSAGE = '绘制面出现自相交,请重新绘制';\r\nconst DBLCLICK_ERROR_MESSAGE = '绘制面存在自相交,请继续绘制';\r\nconst DRAWEND_ERROR_MESSAGE = '绘制面存在自相交,无法完成绘制,请继续绘制或按ESC取消';\r\n\r\n/**\r\n * 判断两条线段是否相交(跨立实验)\r\n * ccw 函数提取到外层,避免每次调用重新创建\r\n */\r\nfunction ccw(A: any, B: any, C: any): boolean {\r\n return (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x);\r\n}\r\n\r\nfunction segmentsIntersect(p1: any, p2: any, p3: any, p4: any): boolean {\r\n return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);\r\n}\r\n\r\nfunction sharesEndpoint(p1: any, p2: any, p3: any, p4: any): boolean {\r\n return (p1.x === p3.x && p1.y === p3.y) ||\r\n (p1.x === p4.x && p1.y === p4.y) ||\r\n (p2.x === p3.x && p2.y === p3.y) ||\r\n (p2.x === p4.x && p2.y === p4.y);\r\n}\r\n\r\nfunction segmentsIntersectSafe(p1: any, p2: any, p3: any, p4: any): boolean {\r\n if (sharesEndpoint(p1, p2, p3, p4)) return false;\r\n return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);\r\n}\r\n\r\n/**\r\n * 自定义 DrawTool,包装 maptalks DrawTool\r\n * 添加功能:在绘制面过程中检测自相交,如果出现自相交则回退到上一个点\r\n */\r\nexport class SelfIntersectionDrawTool {\r\n\r\n private _drawTool: any;\r\n options: SelfIntersectionDrawToolOptions;\r\n private _selfIntersectionHandler: any;\r\n private _hasSelfIntersection: boolean = false;\r\n\r\n constructor(options: SelfIntersectionDrawToolOptions) {\r\n const opts = Object.assign({}, { enableSelfIntersectionCheck: false }, options);\r\n this._drawTool = new maptalks.DrawTool(opts);\r\n this.options = this._drawTool.options;\r\n this._selfIntersectionHandler = this._checkSelfIntersection.bind(this);\r\n }\r\n\r\n /**\r\n * 触发警告\r\n */\r\n private _fireWarning(message: string): void {\r\n this._drawTool._fireEvent('selfintersectionwarning', { type: 'selfintersectionwarning', message });\r\n this.options.onSelfIntersectionError?.(message);\r\n }\r\n\r\n /**\r\n * 获取当前错误消息\r\n */\r\n private _getErrorMessage(defaultMsg: string): string {\r\n return this.options.selfIntersectionErrorMessage || defaultMsg;\r\n }\r\n\r\n /**\r\n * 从坐标中提取环\r\n */\r\n private _getRing(coordinates: any[]): any[] | null {\r\n if (!coordinates || !Array.isArray(coordinates)) return null;\r\n\r\n if (typeof (coordinates[0] as any).x === 'number') {\r\n return coordinates;\r\n }\r\n\r\n if (Array.isArray(coordinates[0]) && Array.isArray(coordinates[0])) {\r\n return coordinates[0];\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 绑定自相交检测事件\r\n */\r\n private _bindSelfIntersectionEvents(): void {\r\n this._drawTool.off('drawvertex', this._selfIntersectionHandler);\r\n\r\n if (!this.options.enableSelfIntersectionCheck) return;\r\n\r\n const mode = this.getMode();\r\n if (mode === 'polygon' || mode === 'freeHandPolygon') {\r\n this._drawTool.on('drawvertex', this._selfIntersectionHandler);\r\n }\r\n }\r\n\r\n /**\r\n * 绑定结束绘制拦截器\r\n */\r\n private _bindEndDrawInterceptor(): void {\r\n // 拦截双击\r\n this._drawTool.on('dblclick', (param: any) => {\r\n if (this._hasSelfIntersection) {\r\n param.domEvent.stopPropagation();\r\n param.domEvent.preventDefault();\r\n this._fireWarning(this._getErrorMessage(DBLCLICK_ERROR_MESSAGE));\r\n }\r\n });\r\n\r\n // 拦截绘制结束\r\n this._drawTool.on('drawend', (param: any) => {\r\n if (!param.geometry || !this._hasSelfIntersection) return;\r\n\r\n param.geometry.remove();\r\n this._hasSelfIntersection = false;\r\n this._fireWarning(this._getErrorMessage(DRAWEND_ERROR_MESSAGE));\r\n });\r\n }\r\n\r\n // ========== DrawTool 方法的代理 ==========\r\n\r\n addTo(map: any): this {\r\n this._drawTool.addTo(map);\r\n this._bindSelfIntersectionEvents();\r\n this._bindEndDrawInterceptor();\r\n return this;\r\n }\r\n\r\n getMode(): string {\r\n return this._drawTool.getMode();\r\n }\r\n\r\n setMode(mode: string): this {\r\n this._drawTool.setMode(mode);\r\n this._hasSelfIntersection = false;\r\n this._bindSelfIntersectionEvents();\r\n return this;\r\n }\r\n\r\n getSymbol(): any {\r\n return this._drawTool.getSymbol();\r\n }\r\n\r\n setSymbol(symbol: any): this {\r\n this._drawTool.setSymbol(symbol);\r\n return this;\r\n }\r\n\r\n getCurrentGeometry(): any {\r\n return this._drawTool.getCurrentGeometry();\r\n }\r\n\r\n undo(): this {\r\n this._drawTool.undo();\r\n return this;\r\n }\r\n\r\n redo(): this {\r\n this._drawTool.redo();\r\n return this;\r\n }\r\n\r\n endDraw(param?: any): this {\r\n this._drawTool.endDraw(param);\r\n return this;\r\n }\r\n\r\n on(eventType: string, handler: any): this {\r\n this._drawTool.on(eventType, handler);\r\n return this;\r\n }\r\n\r\n off(eventType: string, handler: any): this {\r\n this._drawTool.off(eventType, handler);\r\n return this;\r\n }\r\n\r\n enable(): this {\r\n this._drawTool.enable();\r\n return this;\r\n }\r\n\r\n disable(): this {\r\n this._drawTool.disable();\r\n return this;\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this._drawTool.isEnabled();\r\n }\r\n\r\n getMap(): any {\r\n return this._drawTool.getMap();\r\n }\r\n\r\n addCoordinate(coordinate: any): this {\r\n this._drawTool.addCoordinate(coordinate);\r\n return this;\r\n }\r\n\r\n getTempGeometry(): any {\r\n return this._drawTool.getTempGeometry();\r\n }\r\n\r\n setLayerZIndex(zIndex: number): this {\r\n this._drawTool.setLayerZIndex(zIndex);\r\n return this;\r\n }\r\n\r\n // ========== 自相交检测 ==========\r\n\r\n getCurrentCoordinates(): any[] | null {\r\n return this.getCurrentGeometry()?.getCoordinates() || null;\r\n }\r\n\r\n isSelfIntersecting(coordinates: any[]): boolean {\r\n if (!coordinates || coordinates.length === 0) return false;\r\n\r\n const ring = this._getRing(coordinates);\r\n if (!ring || ring.length < 4) return false;\r\n\r\n const n = ring.length;\r\n for (let i = 0; i < n; i++) {\r\n const a1 = ring[i];\r\n const a2 = ring[(i + 1) % n];\r\n\r\n for (let j = 2; j < n; j++) {\r\n if (Math.abs(i - j) <= 1) continue;\r\n if ((i === 0 && j === n - 1) || (j === 0 && i === n - 1)) continue;\r\n\r\n if (segmentsIntersectSafe(a1, a2, ring[j], ring[(j + 1) % n])) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * 检测并处理自相交\r\n */\r\n private _checkSelfIntersection(): void {\r\n const coordinates = this.getCurrentCoordinates();\r\n if (!coordinates) return;\r\n\r\n if (this.isSelfIntersecting(coordinates)) {\r\n this._removeLastVertex();\r\n this._hasSelfIntersection = true;\r\n this._fireWarning(this._getErrorMessage(DEFAULT_ERROR_MESSAGE));\r\n } else {\r\n this._hasSelfIntersection = false;\r\n }\r\n }\r\n\r\n /**\r\n * 移除最后一个顶点\r\n */\r\n private _removeLastVertex(): void {\r\n const geometry = this.getCurrentGeometry();\r\n if (!geometry) return;\r\n\r\n const coords = geometry.getCoordinates();\r\n if (!coords || coords.length === 0) return;\r\n\r\n const clickCoords = this._drawTool._clickCoords;\r\n if (!clickCoords || clickCoords.length === 0) return;\r\n\r\n clickCoords.pop();\r\n this._drawTool._historyPointer = clickCoords.length;\r\n\r\n const ring = this._getRing(coords);\r\n if (ring?.length) {\r\n ring.pop();\r\n geometry.setCoordinates(coords);\r\n }\r\n\r\n const registerMode = this._drawTool._getRegisterMode();\r\n registerMode.update(this._drawTool.getMap().getProjection(), clickCoords, geometry);\r\n }\r\n}\r\n\r\n// UMD 环境下暴露为 window.giserMaptalksDrawTool\r\nif (typeof window !== 'undefined') {\r\n (window as any).giserMaptalksDrawTool = SelfIntersectionDrawTool;\r\n}\r\n\r\nexport default SelfIntersectionDrawTool;"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 自定义 DrawTool 选项
3
+ */
4
+ export interface SelfIntersectionDrawToolOptions {
5
+ mode?: string;
6
+ symbol?: any;
7
+ once?: boolean;
8
+ autoPanAtEdge?: boolean;
9
+ blockGeometryEvents?: boolean;
10
+ zIndex?: number;
11
+ doubleClickZoom?: boolean;
12
+ ignoreMouseleave?: boolean;
13
+ enableAltitude?: boolean;
14
+ interactive?: boolean;
15
+ edgeAutoComplete?: boolean;
16
+ transformCoordinate?: any;
17
+ /** 是否启用自相交检测,默认 false */
18
+ enableSelfIntersectionCheck?: boolean;
19
+ /** 自相交时的提示消息 */
20
+ selfIntersectionErrorMessage?: string;
21
+ /** 自相交检测到时的回调函数 */
22
+ onSelfIntersectionError?: (message: string) => void;
23
+ [key: string]: any;
24
+ }
25
+ /**
26
+ * 自定义 DrawTool,包装 maptalks DrawTool
27
+ * 添加功能:在绘制面过程中检测自相交,如果出现自相交则回退到上一个点
28
+ */
29
+ export declare class SelfIntersectionDrawTool {
30
+ private _drawTool;
31
+ options: SelfIntersectionDrawToolOptions;
32
+ private _selfIntersectionHandler;
33
+ private _hasSelfIntersection;
34
+ constructor(options: SelfIntersectionDrawToolOptions);
35
+ /**
36
+ * 触发警告
37
+ */
38
+ private _fireWarning;
39
+ /**
40
+ * 获取当前错误消息
41
+ */
42
+ private _getErrorMessage;
43
+ /**
44
+ * 从坐标中提取环
45
+ */
46
+ private _getRing;
47
+ /**
48
+ * 绑定自相交检测事件
49
+ */
50
+ private _bindSelfIntersectionEvents;
51
+ /**
52
+ * 绑定结束绘制拦截器
53
+ */
54
+ private _bindEndDrawInterceptor;
55
+ addTo(map: any): this;
56
+ getMode(): string;
57
+ setMode(mode: string): this;
58
+ getSymbol(): any;
59
+ setSymbol(symbol: any): this;
60
+ getCurrentGeometry(): any;
61
+ undo(): this;
62
+ redo(): this;
63
+ endDraw(param?: any): this;
64
+ on(eventType: string, handler: any): this;
65
+ off(eventType: string, handler: any): this;
66
+ enable(): this;
67
+ disable(): this;
68
+ isEnabled(): boolean;
69
+ getMap(): any;
70
+ addCoordinate(coordinate: any): this;
71
+ getTempGeometry(): any;
72
+ setLayerZIndex(zIndex: number): this;
73
+ getCurrentCoordinates(): any[] | null;
74
+ isSelfIntersecting(coordinates: any[]): boolean;
75
+ /**
76
+ * 检测并处理自相交
77
+ */
78
+ private _checkSelfIntersection;
79
+ /**
80
+ * 移除最后一个顶点
81
+ */
82
+ private _removeLastVertex;
83
+ }
84
+ export default SelfIntersectionDrawTool;
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "giser-maptalks-drawtool",
3
+ "version": "1.0.0",
4
+ "description": "maptalks DrawTool extension with self-intersection detection for polygon drawing",
5
+ "main": "dist/giser-maptalks-drawtool.cjs.js",
6
+ "module": "dist/giser-maptalks-drawtool.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "rollup -c",
13
+ "dev": "rollup -c -w"
14
+ },
15
+ "keywords": [
16
+ "maptalks",
17
+ "drawtool",
18
+ "self-intersection",
19
+ "polygon"
20
+ ],
21
+ "peerDependencies": {
22
+ "maptalks": ">=1.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "@rollup/plugin-node-resolve": "^16.0.3",
26
+ "@rollup/plugin-typescript": "^8.5.0",
27
+ "maptalks": "^1.0.0",
28
+ "rollup": "^2.80.0",
29
+ "tslib": "^2.8.1",
30
+ "typescript": "^4.9.5"
31
+ }
32
+ }