plotboilerplate 1.12.10 → 1.16.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 +5 -1
- package/changelog.md +50 -0
- package/dist/index.esm.js +999 -510
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/plotboilerplate.browser.min.js +1 -1
- package/dist/plotboilerplate.browser.min.js.map +1 -1
- package/dist/plotboilerplate.js +1013 -509
- package/dist/plotboilerplate.min.js +1 -1
- package/package.json +1 -1
- package/src/cjs/BezierPath.d.ts +45 -2
- package/src/cjs/BezierPath.js +114 -18
- package/src/cjs/BezierPath.js.map +1 -1
- package/src/cjs/Circle.d.ts +25 -10
- package/src/cjs/Circle.js +38 -33
- package/src/cjs/Circle.js.map +1 -1
- package/src/cjs/CircleSector.d.ts +27 -13
- package/src/cjs/CircleSector.js +38 -23
- package/src/cjs/CircleSector.js.map +1 -1
- package/src/cjs/CubicBezierCurve.d.ts +17 -1
- package/src/cjs/CubicBezierCurve.js +78 -79
- package/src/cjs/CubicBezierCurve.js.map +1 -1
- package/src/cjs/KeyHandler.d.ts +10 -3
- package/src/cjs/KeyHandler.js +28 -23
- package/src/cjs/KeyHandler.js.map +1 -1
- package/src/cjs/Line.d.ts +2 -1
- package/src/cjs/Line.js +19 -18
- package/src/cjs/Line.js.map +1 -1
- package/src/cjs/MouseHandler.js +43 -53
- package/src/cjs/MouseHandler.js.map +1 -1
- package/src/cjs/PBImage.d.ts +16 -1
- package/src/cjs/PBImage.js +13 -3
- package/src/cjs/PBImage.js.map +1 -1
- package/src/cjs/PBText.d.ts +130 -0
- package/src/cjs/PBText.js +76 -0
- package/src/cjs/PBText.js.map +1 -0
- package/src/cjs/PlotBoilerplate.d.ts +2 -1
- package/src/cjs/PlotBoilerplate.js +44 -16
- package/src/cjs/PlotBoilerplate.js.map +1 -1
- package/src/cjs/Polygon.d.ts +37 -1
- package/src/cjs/Polygon.js +131 -54
- package/src/cjs/Polygon.js.map +1 -1
- package/src/cjs/Triangle.d.ts +16 -1
- package/src/cjs/Triangle.js +50 -54
- package/src/cjs/Triangle.js.map +1 -1
- package/src/cjs/VEllipse.d.ts +16 -1
- package/src/cjs/VEllipse.js +25 -12
- package/src/cjs/VEllipse.js.map +1 -1
- package/src/cjs/VEllipseSector.d.ts +15 -1
- package/src/cjs/VEllipseSector.js +11 -1
- package/src/cjs/VEllipseSector.js.map +1 -1
- package/src/cjs/Vector.d.ts +3 -1
- package/src/cjs/Vector.js +32 -36
- package/src/cjs/Vector.js.map +1 -1
- package/src/cjs/VertTuple.d.ts +15 -1
- package/src/cjs/VertTuple.js +14 -19
- package/src/cjs/VertTuple.js.map +1 -1
- package/src/cjs/Vertex.d.ts +66 -4
- package/src/cjs/Vertex.js +99 -17
- package/src/cjs/Vertex.js.map +1 -1
- package/src/cjs/VertexListeners.d.ts +12 -8
- package/src/cjs/VertexListeners.js +18 -25
- package/src/cjs/VertexListeners.js.map +1 -1
- package/src/cjs/draw.d.ts +30 -2
- package/src/cjs/draw.js +51 -6
- package/src/cjs/draw.js.map +1 -1
- package/src/cjs/drawgl.d.ts +29 -2
- package/src/cjs/drawgl.js +21 -4
- package/src/cjs/drawgl.js.map +1 -1
- package/src/cjs/drawutilssvg.d.ts +25 -7
- package/src/cjs/drawutilssvg.js +62 -14
- package/src/cjs/drawutilssvg.js.map +1 -1
- package/src/cjs/entry.js +1 -0
- package/src/cjs/index.d.ts +1 -0
- package/src/cjs/index.js +1 -0
- package/src/cjs/index.js.map +1 -1
- package/src/cjs/interfaces/DrawLib.d.ts +27 -6
- package/src/cjs/interfaces/DrawLib.js +3 -0
- package/src/cjs/interfaces/DrawLib.js.map +1 -1
- package/src/cjs/interfaces/core.d.ts +9 -1
- package/src/cjs/interfaces/core.js +1 -0
- package/src/cjs/interfaces/core.js.map +1 -1
- package/src/cjs/utils/creategui.js +1 -1
- package/src/cjs/utils/findInVertexArray.d.ts +19 -0
- package/src/cjs/utils/findInVertexArray.js +29 -0
- package/src/cjs/utils/findInVertexArray.js.map +1 -0
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.d.ts +15 -0
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.js +55 -28
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
- package/src/cjs/utils/io/DndFileHandler.d.ts +63 -0
- package/src/cjs/utils/io/DndFileHandler.js +112 -0
- package/src/cjs/utils/io/DndFileHandler.js.map +1 -0
- package/src/cjs/utils/io/FileDrop.d.ts +98 -0
- package/src/cjs/utils/io/FileDrop.js +142 -0
- package/src/cjs/utils/io/FileDrop.js.map +1 -0
- package/src/esm/BezierPath.d.ts +45 -2
- package/src/esm/BezierPath.js +114 -18
- package/src/esm/BezierPath.js.map +1 -1
- package/src/esm/Circle.d.ts +25 -10
- package/src/esm/Circle.js +38 -33
- package/src/esm/Circle.js.map +1 -1
- package/src/esm/CircleSector.d.ts +27 -13
- package/src/esm/CircleSector.js +38 -23
- package/src/esm/CircleSector.js.map +1 -1
- package/src/esm/CubicBezierCurve.d.ts +17 -1
- package/src/esm/CubicBezierCurve.js +78 -79
- package/src/esm/CubicBezierCurve.js.map +1 -1
- package/src/esm/KeyHandler.d.ts +10 -3
- package/src/esm/KeyHandler.js +28 -23
- package/src/esm/KeyHandler.js.map +1 -1
- package/src/esm/Line.d.ts +2 -1
- package/src/esm/Line.js +19 -18
- package/src/esm/Line.js.map +1 -1
- package/src/esm/MouseHandler.js +43 -53
- package/src/esm/MouseHandler.js.map +1 -1
- package/src/esm/PBImage.d.ts +16 -1
- package/src/esm/PBImage.js +13 -3
- package/src/esm/PBImage.js.map +1 -1
- package/src/esm/PBText.d.ts +130 -0
- package/src/esm/PBText.js +71 -0
- package/src/esm/PBText.js.map +1 -0
- package/src/esm/PlotBoilerplate.d.ts +2 -1
- package/src/esm/PlotBoilerplate.js +44 -16
- package/src/esm/PlotBoilerplate.js.map +1 -1
- package/src/esm/Polygon.d.ts +37 -1
- package/src/esm/Polygon.js +131 -54
- package/src/esm/Polygon.js.map +1 -1
- package/src/esm/Triangle.d.ts +16 -1
- package/src/esm/Triangle.js +50 -54
- package/src/esm/Triangle.js.map +1 -1
- package/src/esm/VEllipse.d.ts +16 -1
- package/src/esm/VEllipse.js +25 -12
- package/src/esm/VEllipse.js.map +1 -1
- package/src/esm/VEllipseSector.d.ts +15 -1
- package/src/esm/VEllipseSector.js +11 -1
- package/src/esm/VEllipseSector.js.map +1 -1
- package/src/esm/Vector.d.ts +3 -1
- package/src/esm/Vector.js +32 -36
- package/src/esm/Vector.js.map +1 -1
- package/src/esm/VertTuple.d.ts +15 -1
- package/src/esm/VertTuple.js +14 -19
- package/src/esm/VertTuple.js.map +1 -1
- package/src/esm/Vertex.d.ts +66 -4
- package/src/esm/Vertex.js +99 -17
- package/src/esm/Vertex.js.map +1 -1
- package/src/esm/VertexListeners.d.ts +12 -8
- package/src/esm/VertexListeners.js +18 -25
- package/src/esm/VertexListeners.js.map +1 -1
- package/src/esm/draw.d.ts +30 -2
- package/src/esm/draw.js +51 -6
- package/src/esm/draw.js.map +1 -1
- package/src/esm/drawgl.d.ts +29 -2
- package/src/esm/drawgl.js +21 -4
- package/src/esm/drawgl.js.map +1 -1
- package/src/esm/drawutilssvg.d.ts +25 -7
- package/src/esm/drawutilssvg.js +62 -14
- package/src/esm/drawutilssvg.js.map +1 -1
- package/src/esm/entry.js +1 -0
- package/src/esm/index.d.ts +1 -0
- package/src/esm/index.js +1 -0
- package/src/esm/index.js.map +1 -1
- package/src/esm/interfaces/DrawLib.d.ts +27 -6
- package/src/esm/interfaces/DrawLib.js +3 -0
- package/src/esm/interfaces/DrawLib.js.map +1 -1
- package/src/esm/interfaces/core.d.ts +9 -1
- package/src/esm/interfaces/core.js +1 -0
- package/src/esm/interfaces/core.js.map +1 -1
- package/src/esm/utils/findInVertexArray.d.ts +19 -0
- package/src/esm/utils/findInVertexArray.js +25 -0
- package/src/esm/utils/findInVertexArray.js.map +1 -0
- package/src/esm/utils/helpers/BezierPathInteractionHelper.d.ts +15 -0
- package/src/esm/utils/helpers/BezierPathInteractionHelper.js +54 -28
- package/src/esm/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
- package/src/esm/utils/io/DndFileHandler.d.ts +63 -0
- package/src/esm/utils/io/DndFileHandler.js +106 -0
- package/src/esm/utils/io/DndFileHandler.js.map +1 -0
- package/src/esm/utils/io/FileDrop.d.ts +98 -0
- package/src/esm/utils/io/FileDrop.js +136 -0
- package/src/esm/utils/io/FileDrop.js.map +1 -0
- package/src/ts/BezierPath.ts +133 -16
- package/src/ts/Circle.ts +213 -200
- package/src/ts/CircleSector.ts +171 -141
- package/src/ts/CubicBezierCurve.ts +777 -810
- package/src/ts/KeyHandler.ts +221 -212
- package/src/ts/Line.ts +77 -80
- package/src/ts/MouseHandler.ts +356 -368
- package/src/ts/PBImage.ts +81 -68
- package/src/ts/PBText.ts +166 -0
- package/src/ts/PlotBoilerplate.ts +48 -20
- package/src/ts/Polygon.ts +519 -451
- package/src/ts/Triangle.ts +484 -489
- package/src/ts/VEllipse.ts +36 -11
- package/src/ts/VEllipseSector.ts +20 -1
- package/src/ts/Vector.ts +164 -160
- package/src/ts/VertTuple.ts +333 -338
- package/src/ts/Vertex.ts +117 -16
- package/src/ts/VertexListeners.ts +248 -266
- package/src/ts/draw.ts +71 -8
- package/src/ts/drawgl.ts +48 -8
- package/src/ts/drawutilssvg.ts +94 -17
- package/src/ts/index.ts +1 -0
- package/src/ts/interfaces/DrawLib.ts +30 -4
- package/src/ts/interfaces/core.ts +9 -0
- package/src/ts/utils/findInVertexArray.ts +28 -0
- package/src/ts/utils/helpers/BezierPathInteractionHelper.ts +61 -30
- package/src/ts/utils/io/FileDrop.ts +178 -0
- package/dist/plotboilerplate.browser.min.js.LICENSE.txt +0 -8
- package/src/ts/utils/algorithms/clearPolygonDuplicateVertices.ts~ +0 -5
- package/src/ts/utils/algorithms/findPolygonSelfIntersections.ts~ +0 -45
- package/src/ts/utils/algorithms/sh-tmp.ts~ +0 -59
- package/src/ts/utils/algorithms/splitPolygonToNonIntersecting.ts~ +0 -113
- package/src/ts/utils/algorithms/sutherlandHodgman.ts~ +0 -88
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A basic IO handler for file drop (Drag-and-drop).
|
|
3
|
+
*
|
|
4
|
+
* Example use:
|
|
5
|
+
* ```javascript
|
|
6
|
+
* var body = document.getElememtByTagName("body")[0];
|
|
7
|
+
* var fileDrop = new FileDrop(body);
|
|
8
|
+
* fileDrop.onFileJSONDropped(function (jsonObject) {
|
|
9
|
+
* console.log("jsonObject", jsonObject);
|
|
10
|
+
* });
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @author Ikaros Kappler
|
|
14
|
+
* @date 2021-10-13
|
|
15
|
+
* @modified 2022-01-31 (ported from the ngdg project, then generalized)
|
|
16
|
+
* @version 2.0.0
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
type IDroppedCallbackJSON = (jsonData: object) => void;
|
|
20
|
+
type IDroppedCallbackText = (textData: string) => void;
|
|
21
|
+
type IDroppedCallbackBinary = (binaryData: Blob, file: File) => void;
|
|
22
|
+
|
|
23
|
+
export class FileDrop {
|
|
24
|
+
/**
|
|
25
|
+
* The 'dropzone' element.
|
|
26
|
+
* @private
|
|
27
|
+
* @memberof FileDrop
|
|
28
|
+
* @member {HTMLElement}
|
|
29
|
+
*/
|
|
30
|
+
private element: HTMLElement;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The JSON file drop callback.
|
|
34
|
+
* @private
|
|
35
|
+
* @memberof FileDrop
|
|
36
|
+
* @member {HTMLElement}
|
|
37
|
+
*/
|
|
38
|
+
private fileDroppedCallbackJSON: IDroppedCallbackJSON | null;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The text file drop callback.
|
|
42
|
+
* @private
|
|
43
|
+
* @memberof FileDrop
|
|
44
|
+
* @member {HTMLElement}
|
|
45
|
+
*/
|
|
46
|
+
private fileDroppedCallbackText: IDroppedCallbackText | null;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The binary file drop callback.
|
|
50
|
+
* @private
|
|
51
|
+
* @memberof FileDrop
|
|
52
|
+
* @member {HTMLElement}
|
|
53
|
+
*/
|
|
54
|
+
private fileDroppedCallbackBinary: IDroppedCallbackBinary | null;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {HTMLElement} element - The element you wish to operate as the drop zone (like <body/>).
|
|
59
|
+
*/
|
|
60
|
+
constructor(element: HTMLElement) {
|
|
61
|
+
this.element = element;
|
|
62
|
+
|
|
63
|
+
// Init the drop listeners
|
|
64
|
+
element.addEventListener("drop", this.handleDropEvent.bind(this));
|
|
65
|
+
element.addEventListener("dragover", this.handleDragOverEvent.bind(this));
|
|
66
|
+
element.addEventListener("dragleave", this.handleDragLeaveEvent.bind(this));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Install the JSON (MIME type json*) file drop callback. Note than only one callback can be installed
|
|
71
|
+
* in this implementation. Calling this method multiple times will overwrite previously
|
|
72
|
+
* installed listeners.
|
|
73
|
+
*
|
|
74
|
+
* The callback will receive the dropped file content as an object (parsed JSON).
|
|
75
|
+
*
|
|
76
|
+
* @param {(data:object)=>void} callback
|
|
77
|
+
*/
|
|
78
|
+
onFileJSONDropped(callback: IDroppedCallbackJSON) {
|
|
79
|
+
this.fileDroppedCallbackJSON = callback;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Install the text file (MIME type text/plain) drop callback. Note than only one callback can be installed
|
|
84
|
+
* in this implementation. Calling this method multiple times will overwrite previously
|
|
85
|
+
* installed listeners.
|
|
86
|
+
*
|
|
87
|
+
* The callback will receive the dropped file content as a string.
|
|
88
|
+
*
|
|
89
|
+
* @param {(data:object)=>void} callback
|
|
90
|
+
*/
|
|
91
|
+
onFileTextDropped(callback: IDroppedCallbackText) {
|
|
92
|
+
this.fileDroppedCallbackText = callback;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Internally handle a drop event.
|
|
97
|
+
*
|
|
98
|
+
* @param {DragEvent} event
|
|
99
|
+
* @returns {void}
|
|
100
|
+
*/
|
|
101
|
+
private handleDropEvent = (event: DragEvent) => {
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
event.stopPropagation();
|
|
104
|
+
this.element.style.opacity = "1.0";
|
|
105
|
+
|
|
106
|
+
if (!event.dataTransfer.files || event.dataTransfer.files.length === 0) {
|
|
107
|
+
// No files were dropped
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (event.dataTransfer.files.length > 1) {
|
|
111
|
+
// Multiple file drop is not nupported
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (!this.fileDroppedCallbackJSON) {
|
|
115
|
+
// No handling callback defined.
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (event.dataTransfer.files[0]) {
|
|
119
|
+
const file: File = event.dataTransfer.files[0];
|
|
120
|
+
// console.log("file", file);
|
|
121
|
+
if (file.type.match(/json.*/) && this.fileDroppedCallbackJSON) {
|
|
122
|
+
var reader = new FileReader();
|
|
123
|
+
reader.onload = (readEvent: ProgressEvent<FileReader>) => {
|
|
124
|
+
// Finished reading file data.
|
|
125
|
+
const jsonObject: object = JSON.parse(readEvent.target.result as string);
|
|
126
|
+
// TODO: what happens on fail?
|
|
127
|
+
this.fileDroppedCallbackJSON(jsonObject);
|
|
128
|
+
};
|
|
129
|
+
reader.readAsText(file); // start reading the file data.
|
|
130
|
+
} else if (file.type.match(/text\/plain.*/) && this.fileDroppedCallbackText) {
|
|
131
|
+
var reader = new FileReader();
|
|
132
|
+
reader.onload = (readEvent: ProgressEvent<FileReader>) => {
|
|
133
|
+
// Finished reading file data.
|
|
134
|
+
this.fileDroppedCallbackText(readEvent.target.result as string);
|
|
135
|
+
};
|
|
136
|
+
reader.readAsText(file); // start reading the file data.
|
|
137
|
+
} else if (this.fileDroppedCallbackBinary) {
|
|
138
|
+
var reader = new FileReader();
|
|
139
|
+
reader.onload = (readEvent: ProgressEvent<FileReader>) => {
|
|
140
|
+
// Finished reading file data.
|
|
141
|
+
this.fileDroppedCallbackBinary(new Blob([readEvent.target.result]), file);
|
|
142
|
+
};
|
|
143
|
+
reader.readAsBinaryString(file); // start reading the file data.
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Toggles the drop sensitive element's opacity to 0.5.
|
|
150
|
+
*
|
|
151
|
+
* @param {DragEvent} event - The event.
|
|
152
|
+
*/
|
|
153
|
+
private handleDragOverEvent = (event: DragEvent) => {
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
event.stopPropagation();
|
|
156
|
+
this.element.style.opacity = "0.5";
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Restored the drop sensitive element's opacity back to 1.0.
|
|
161
|
+
*
|
|
162
|
+
* @param {DragEvent} event - The event.
|
|
163
|
+
*/
|
|
164
|
+
private handleDragLeaveEvent = (event: DragEvent) => {
|
|
165
|
+
event.preventDefault();
|
|
166
|
+
event.stopPropagation();
|
|
167
|
+
this.element.style.opacity = "1.0";
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Removes all listeners (drop, dragover and dragleave).
|
|
172
|
+
*/
|
|
173
|
+
destroy() {
|
|
174
|
+
this.element.removeEventListener("drop", this.handleDropEvent);
|
|
175
|
+
this.element.removeEventListener("dragover", this.handleDragOverEvent);
|
|
176
|
+
this.element.removeEventListener("dragleave", this.handleDragLeaveEvent);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @requires Line
|
|
3
|
-
* @requires Vertex
|
|
4
|
-
*
|
|
5
|
-
* @author Ikaros Kappler
|
|
6
|
-
* @date 2020-12-04
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Collect all self-intersection points of the given polygon.
|
|
12
|
-
*
|
|
13
|
-
* @name findPolygonSelfIntersections
|
|
14
|
-
* @param {Array<Vertex>} polygon
|
|
15
|
-
* @return Array<Vertex>
|
|
16
|
-
*/
|
|
17
|
-
var findPolygonSelfIntersections = function( polygon ) {
|
|
18
|
-
var pointList = [];
|
|
19
|
-
var lineA = new Line( new Vertex(), new Vertex() );
|
|
20
|
-
var lineB = new Line( new Vertex(), new Vertex() );
|
|
21
|
-
for( var a = 0; a < polygon.vertices.length; a++ ) {
|
|
22
|
-
lineA.a.set( polygon.getVertexAt(a) );
|
|
23
|
-
lineA.b.set( polygon.getVertexAt(a+1) );
|
|
24
|
-
for( var b = 0; b < polygon.vertices.length; b++ ) {
|
|
25
|
-
// Same edge or neighbour edges intersect by definition.
|
|
26
|
-
// Skip them.
|
|
27
|
-
if( a == b || a+1 == b || a == b+1
|
|
28
|
-
|| (a==0&&b+1==polygon.vertices.length) || (b==0&&a+1==polygon.vertices.length) )
|
|
29
|
-
continue;
|
|
30
|
-
lineB.a.set( polygon.getVertexAt(b) );
|
|
31
|
-
lineB.b.set( polygon.getVertexAt(b+1) );
|
|
32
|
-
|
|
33
|
-
// Commpute the intersection point of the (infinite) lines.
|
|
34
|
-
// The point is undefined if and only if both line are parallel (co-linear).
|
|
35
|
-
const intersectionPoint = lineA.intersection(lineB);
|
|
36
|
-
|
|
37
|
-
// Check if the intersection point is on both (finite) edges of the polygon.
|
|
38
|
-
if( intersectionPoint
|
|
39
|
-
&& lineA.hasPoint(intersectionPoint) && lineB.hasPoint(intersectionPoint) ) {
|
|
40
|
-
pointList.push( intersectionPoint );
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return pointList;
|
|
45
|
-
};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
interface XYCoords {
|
|
3
|
-
x : number;
|
|
4
|
-
y : number;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
const inside = ( cp1 : XYCoords, cp2 : XYCoords, p : XYCoords) : boolean => {
|
|
8
|
-
return (cp2.x-cp1.x)*(p.y-cp1.y) > (cp2.y-cp1.y)*(p.x-cp1.x);
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const intersection = ( cp1 : XYCoords ,cp2 : XYCoords ,s : XYCoords, e : XYCoords ) : XYCoords => {
|
|
12
|
-
const dc = {
|
|
13
|
-
x: cp1.x - cp2.x,
|
|
14
|
-
y : cp1.y - cp2.y
|
|
15
|
-
},
|
|
16
|
-
dp = { x: s.x - e.x,
|
|
17
|
-
y : s.y - e.y
|
|
18
|
-
},
|
|
19
|
-
n1 = cp1.x * cp2.y - cp1.y * cp2.x,
|
|
20
|
-
n2 = s.x * e.y - s.y * e.x,
|
|
21
|
-
n3 = 1.0 / (dc.x * dp.y - dc.y * dp.x);
|
|
22
|
-
return { x : (n1*dp.x - n2*dc.x) * n3,
|
|
23
|
-
y : (n1*dp.y - n2*dc.y) * n3
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const sutherlandHodgman = ( subjectPolygon : Array<XYCoords>,
|
|
28
|
-
clipPolygon : Array<XYCoords> ) : Array<XYCoords> => {
|
|
29
|
-
|
|
30
|
-
let cp1 : XYCoords = clipPolygon[clipPolygon.length-1];
|
|
31
|
-
let cp2 : XYCoords;
|
|
32
|
-
let s : XYCoords;
|
|
33
|
-
let e : XYCoords;
|
|
34
|
-
|
|
35
|
-
let outputList : Array<XYCoords> = subjectPolygon;
|
|
36
|
-
|
|
37
|
-
for( var j in clipPolygon ) {
|
|
38
|
-
cp2 = clipPolygon[j];
|
|
39
|
-
var inputList = outputList;
|
|
40
|
-
outputList = [];
|
|
41
|
-
s = inputList[inputList.length - 1]; // last on the input list
|
|
42
|
-
for (var i in inputList) {
|
|
43
|
-
e = inputList[i];
|
|
44
|
-
if (inside(cp1,cp2,e)) {
|
|
45
|
-
if (!inside(cp1,cp2,s)) {
|
|
46
|
-
outputList.push(intersection(cp1,cp2,s,e));
|
|
47
|
-
}
|
|
48
|
-
outputList.push(e);
|
|
49
|
-
}
|
|
50
|
-
else if (inside(cp1,cp2,s)) {
|
|
51
|
-
outputList.push(intersection(cp1,cp2,s,e));
|
|
52
|
-
}
|
|
53
|
-
s = e;
|
|
54
|
-
}
|
|
55
|
-
cp1 = cp2;
|
|
56
|
-
}
|
|
57
|
-
return outputList
|
|
58
|
-
}
|
|
59
|
-
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This function cuts a given self-intersecting polygon into non-self-intersecting
|
|
3
|
-
* sub polygons.
|
|
4
|
-
*
|
|
5
|
-
* The algorithm only works for non-self-overlapping polygons.
|
|
6
|
-
* Please note that the union set of the sub polygons themselves will _not_ be disjunct if
|
|
7
|
-
* the input polyon overlaps with itself!
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* @requires Line
|
|
11
|
-
* @requires Vertex
|
|
12
|
-
* @requires greinerHormann
|
|
13
|
-
*
|
|
14
|
-
* @date 2020-12-04
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
(function(_context) {
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @param {Array<Vertex>} vertices
|
|
21
|
-
* @param {number=10} maxDepth
|
|
22
|
-
*/
|
|
23
|
-
var splitToNonIntersectingPolygons = function( vertices, maxDepth ) {
|
|
24
|
-
if( typeof maxDepth === "undefined" )
|
|
25
|
-
maxDepth = 10;
|
|
26
|
-
return _splitToNonIntersectingPolygons( vertices, maxDepth );
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
var _splitToNonIntersectingPolygons = function( vertices, maxDepth ) {
|
|
31
|
-
|
|
32
|
-
if( maxDepth <= 0 ) {
|
|
33
|
-
console.log('aborting at max depth');
|
|
34
|
-
return [ vertices ];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if( vertices.length <= 3 ) {
|
|
38
|
-
// No intersections possible
|
|
39
|
-
return [ vertices ];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// var pointList = [];
|
|
43
|
-
var n = vertices.length;
|
|
44
|
-
var lineA = new Line( new Vertex(), new Vertex() );
|
|
45
|
-
var lineB = new Line( new Vertex(), new Vertex() );
|
|
46
|
-
for( var a = 0; a < vertices.length; a++ ) {
|
|
47
|
-
lineA.a.set( vertices[a] );
|
|
48
|
-
lineA.b.set( vertices[(a+1) % n] );
|
|
49
|
-
for( var b = 0; b < vertices.length; b++ ) {
|
|
50
|
-
// Equal or neighbour edges intersect by definition.
|
|
51
|
-
// We ignore them.
|
|
52
|
-
if( a == b || a+1 == b || a == b+1 || (a==0&&b+1==vertices.length) || (b==0&&a+1==vertices.length) )
|
|
53
|
-
continue;
|
|
54
|
-
lineB.a.set( vertices[b] );
|
|
55
|
-
lineB.b.set( vertices[(b+1) % n] );
|
|
56
|
-
|
|
57
|
-
const intersectionPoint = lineA.intersection(lineB);
|
|
58
|
-
// console.log( 'intersectionPoint', intersectionPoint );
|
|
59
|
-
if( intersectionPoint && lineA.hasPoint(intersectionPoint) && lineB.hasPoint(intersectionPoint) ) {
|
|
60
|
-
// console.log( 'intersection found' );
|
|
61
|
-
// pointList.push( intersectionPoint );
|
|
62
|
-
// Cut polygon into two here
|
|
63
|
-
var split = splitPolygonAt( vertices, a, b, intersectionPoint );
|
|
64
|
-
|
|
65
|
-
// Split has 2 elements.
|
|
66
|
-
var leftCleaned = _splitToNonIntersectingPolygons( split[0], maxDepth-1 );
|
|
67
|
-
var rightCleaned = _splitToNonIntersectingPolygons( split[1], maxDepth-1 );
|
|
68
|
-
|
|
69
|
-
return leftCleaned.concat( rightCleaned );
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// console.log( 'intersectionPoints', pointList );
|
|
74
|
-
|
|
75
|
-
// No intersection found:
|
|
76
|
-
// just return a list with the original
|
|
77
|
-
// polygon as its only element.
|
|
78
|
-
return [ vertices ];
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// Pre: edgeIndexA < edgeIndexB && vertices.length >= 4
|
|
83
|
-
var splitPolygonAt = function( vertices, edgeIndexA, edgeIndexB, intersectionPoint ) {
|
|
84
|
-
|
|
85
|
-
// console.log( 'split', edgeIndexA, edgeIndexB );
|
|
86
|
-
|
|
87
|
-
var first = [];
|
|
88
|
-
var second = [];
|
|
89
|
-
for( var i = 0; i < vertices.length; i++ ) {
|
|
90
|
-
if( i <= edgeIndexA )
|
|
91
|
-
first.push( vertices[i] );
|
|
92
|
-
|
|
93
|
-
if( i == edgeIndexA ) {
|
|
94
|
-
first.push( intersectionPoint );
|
|
95
|
-
second.push( intersectionPoint ); // clone???
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if( i > edgeIndexA && i <= edgeIndexB )
|
|
99
|
-
second.push( vertices[i] );
|
|
100
|
-
|
|
101
|
-
if( i > edgeIndexB )
|
|
102
|
-
first.push( vertices[i] );
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// console.log( 'split', first, second );
|
|
107
|
-
|
|
108
|
-
return [ first, second ];
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
_context.splitToNonIntersectingPolygons = splitToNonIntersectingPolygons;
|
|
112
|
-
|
|
113
|
-
})(globalThis || window);
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The Sutherland-Hodgman convex polygon clipping algorithm.
|
|
5
|
-
*
|
|
6
|
-
* Converted to Vertex variant {x:number,y:number} by Ikaros Kappler.
|
|
7
|
-
*
|
|
8
|
-
* @date 2021-01-29
|
|
9
|
-
* @version 1.0.0
|
|
10
|
-
*
|
|
11
|
-
* Original version:
|
|
12
|
-
* https://rosettacode.org/wiki/Sutherland-Hodgman_polygon_clipping#JavaScript
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
(function() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @param {Vertex}
|
|
22
|
-
* @param {Vertex}
|
|
23
|
-
**/
|
|
24
|
-
var inside = function (_cp1,_cp2,p) {
|
|
25
|
-
// console.log('x', _cp1);
|
|
26
|
-
return (_cp2.x-_cp1.x)*(p.y-_cp1.y) > (_cp2.y-_cp1.y)*(p.x-_cp1.x);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {Vertex}
|
|
31
|
-
* @param {Vertex}
|
|
32
|
-
* @param {Vertex}
|
|
33
|
-
* @param {Vertex}
|
|
34
|
-
*/
|
|
35
|
-
var intersection = function (_cp1,_cp2,_s,_e) {
|
|
36
|
-
var
|
|
37
|
-
dc = { x: _cp1.x - _cp2.x,
|
|
38
|
-
y : _cp1.y - _cp2.y
|
|
39
|
-
},
|
|
40
|
-
dp = { x: _s.x - _e.x,
|
|
41
|
-
y : _s.y - _e.y
|
|
42
|
-
},
|
|
43
|
-
n1 = _cp1.x * _cp2.y - _cp1.y * _cp2.x,
|
|
44
|
-
n2 = _s.x * _e.y - _s.y * _e.x,
|
|
45
|
-
n3 = 1.0 / (dc.x * dp.y - dc.y * dp.x);
|
|
46
|
-
return { x : (n1*dp.x - n2*dc.x) * n3,
|
|
47
|
-
y : (n1*dp.y - n2*dc.y) * n3
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @param {Array<Vertex>} subjectPolygon
|
|
54
|
-
* @param {Array<Vertex>} clipPolygon - Must be convex.
|
|
55
|
-
*/
|
|
56
|
-
var sutherlandHodgman = function(subjectPolygon, clipPolygon) {
|
|
57
|
-
|
|
58
|
-
var cp1, cp2, s, e;
|
|
59
|
-
|
|
60
|
-
var outputList = subjectPolygon;
|
|
61
|
-
cp1 = clipPolygon[clipPolygon.length-1];
|
|
62
|
-
|
|
63
|
-
for (var j in clipPolygon) {
|
|
64
|
-
var cp2 = clipPolygon[j];
|
|
65
|
-
var inputList = outputList;
|
|
66
|
-
outputList = [];
|
|
67
|
-
s = inputList[inputList.length - 1]; // last on the input list
|
|
68
|
-
for (var i in inputList) {
|
|
69
|
-
var e = inputList[i];
|
|
70
|
-
if (inside(cp1,cp2,e)) {
|
|
71
|
-
if (!inside(cp1,cp2,s)) {
|
|
72
|
-
outputList.push(intersection(cp1,cp2,s,e));
|
|
73
|
-
}
|
|
74
|
-
outputList.push(e);
|
|
75
|
-
}
|
|
76
|
-
else if (inside(cp1,cp2,s)) {
|
|
77
|
-
outputList.push(intersection(cp1,cp2,s,e));
|
|
78
|
-
}
|
|
79
|
-
s = e;
|
|
80
|
-
}
|
|
81
|
-
cp1 = cp2;
|
|
82
|
-
}
|
|
83
|
-
return outputList
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
globalThis.sutherlandHodgman = sutherlandHodgman;
|
|
87
|
-
|
|
88
|
-
})();
|