plotboilerplate 1.20.2 → 1.22.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.
Files changed (169) hide show
  1. package/dist/index.esm.js +2012 -1366
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/index.esm.min.js +1 -1
  4. package/dist/index.esm.min.js.map +1 -1
  5. package/dist/plotboilerplate.browser.min.js +1 -1
  6. package/dist/plotboilerplate.browser.min.js.map +1 -1
  7. package/dist/plotboilerplate.js +1199 -541
  8. package/dist/plotboilerplate.min.js +1 -1
  9. package/package.json +3 -2
  10. package/src/cjs/BezierPath.d.ts +27 -49
  11. package/src/cjs/BezierPath.js +67 -234
  12. package/src/cjs/BezierPath.js.map +1 -1
  13. package/src/cjs/Bounds.d.ts +14 -1
  14. package/src/cjs/Bounds.js +21 -1
  15. package/src/cjs/Bounds.js.map +1 -1
  16. package/src/cjs/CubicBezierCurve.d.ts +70 -1
  17. package/src/cjs/CubicBezierCurve.js +130 -12
  18. package/src/cjs/CubicBezierCurve.js.map +1 -1
  19. package/src/cjs/Line.d.ts +2 -1
  20. package/src/cjs/Line.js +1 -0
  21. package/src/cjs/Line.js.map +1 -1
  22. package/src/cjs/PBText.d.ts +2 -1
  23. package/src/cjs/PBText.js +10 -9
  24. package/src/cjs/PBText.js.map +1 -1
  25. package/src/cjs/PlotBoilerplate.d.ts +4 -13
  26. package/src/cjs/PlotBoilerplate.js +61 -15
  27. package/src/cjs/PlotBoilerplate.js.map +1 -1
  28. package/src/cjs/Polygon.d.ts +47 -1
  29. package/src/cjs/Polygon.js +116 -1
  30. package/src/cjs/Polygon.js.map +1 -1
  31. package/src/cjs/VEllipse.js +1 -1
  32. package/src/cjs/VEllipse.js.map +1 -1
  33. package/src/cjs/Vector.d.ts +4 -4
  34. package/src/cjs/Vector.js +2 -2
  35. package/src/cjs/Vector.js.map +1 -1
  36. package/src/cjs/VertTuple.d.ts +2 -1
  37. package/src/cjs/VertTuple.js +4 -3
  38. package/src/cjs/VertTuple.js.map +1 -1
  39. package/src/cjs/Vertex.d.ts +14 -3
  40. package/src/cjs/Vertex.js +18 -3
  41. package/src/cjs/Vertex.js.map +1 -1
  42. package/src/cjs/draw.d.ts +154 -75
  43. package/src/cjs/draw.js +308 -137
  44. package/src/cjs/draw.js.map +1 -1
  45. package/src/cjs/drawgl.d.ts +87 -50
  46. package/src/cjs/drawgl.js +86 -31
  47. package/src/cjs/drawgl.js.map +1 -1
  48. package/src/cjs/drawutilssvg.d.ts +226 -53
  49. package/src/cjs/drawutilssvg.js +374 -92
  50. package/src/cjs/drawutilssvg.js.map +1 -1
  51. package/src/cjs/interfaces/DrawLib.d.ts +157 -79
  52. package/src/cjs/interfaces/DrawLib.js +6 -0
  53. package/src/cjs/interfaces/DrawLib.js.map +1 -1
  54. package/src/cjs/interfaces/core.d.ts +13 -2
  55. package/src/cjs/interfaces/core.js +1 -0
  56. package/src/cjs/interfaces/core.js.map +1 -1
  57. package/src/cjs/utils/Params.d.ts +15 -0
  58. package/src/cjs/utils/Params.js +49 -0
  59. package/src/cjs/utils/Params.js.map +1 -0
  60. package/src/cjs/utils/algorithms/ContourLineDetection.d.ts +150 -0
  61. package/src/cjs/utils/algorithms/ContourLineDetection.js +367 -0
  62. package/src/cjs/utils/algorithms/ContourLineDetection.js.map +1 -0
  63. package/src/cjs/utils/algorithms/clearDuplicateVertices.d.ts +21 -0
  64. package/src/cjs/utils/algorithms/clearDuplicateVertices.js +48 -0
  65. package/src/cjs/utils/algorithms/clearDuplicateVertices.js.map +1 -0
  66. package/src/cjs/utils/creategui.js +16 -10
  67. package/src/cjs/utils/datastructures/DataGrid2d.d.ts +47 -0
  68. package/src/cjs/utils/datastructures/DataGrid2d.js +20 -0
  69. package/src/cjs/utils/datastructures/DataGrid2d.js.map +1 -0
  70. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.d.ts +65 -0
  71. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.js +84 -0
  72. package/src/cjs/utils/datastructures/DataGrid2dListAdapter.js.map +1 -0
  73. package/src/cjs/utils/datastructures/GenericPath.d.ts +14 -3
  74. package/src/cjs/utils/datastructures/GenericPath.js +20 -3
  75. package/src/cjs/utils/datastructures/GenericPath.js.map +1 -1
  76. package/src/cjs/utils/detectDarkMode.d.ts +10 -0
  77. package/src/cjs/utils/detectDarkMode.js +32 -0
  78. package/src/cjs/utils/detectDarkMode.js.map +1 -0
  79. package/src/esm/BezierPath.d.ts +27 -49
  80. package/src/esm/BezierPath.js +67 -234
  81. package/src/esm/BezierPath.js.map +1 -1
  82. package/src/esm/Bounds.d.ts +14 -1
  83. package/src/esm/Bounds.js +19 -1
  84. package/src/esm/Bounds.js.map +1 -1
  85. package/src/esm/CubicBezierCurve.d.ts +70 -1
  86. package/src/esm/CubicBezierCurve.js +130 -12
  87. package/src/esm/CubicBezierCurve.js.map +1 -1
  88. package/src/esm/Line.d.ts +2 -1
  89. package/src/esm/Line.js +1 -0
  90. package/src/esm/Line.js.map +1 -1
  91. package/src/esm/PBText.d.ts +2 -1
  92. package/src/esm/PBText.js +10 -9
  93. package/src/esm/PBText.js.map +1 -1
  94. package/src/esm/PlotBoilerplate.d.ts +4 -13
  95. package/src/esm/PlotBoilerplate.js +62 -16
  96. package/src/esm/PlotBoilerplate.js.map +1 -1
  97. package/src/esm/Polygon.d.ts +47 -1
  98. package/src/esm/Polygon.js +114 -1
  99. package/src/esm/Polygon.js.map +1 -1
  100. package/src/esm/VEllipse.js +1 -1
  101. package/src/esm/VEllipse.js.map +1 -1
  102. package/src/esm/Vector.d.ts +4 -4
  103. package/src/esm/Vector.js +2 -2
  104. package/src/esm/Vector.js.map +1 -1
  105. package/src/esm/VertTuple.d.ts +2 -1
  106. package/src/esm/VertTuple.js +4 -3
  107. package/src/esm/VertTuple.js.map +1 -1
  108. package/src/esm/Vertex.d.ts +14 -3
  109. package/src/esm/Vertex.js +18 -3
  110. package/src/esm/Vertex.js.map +1 -1
  111. package/src/esm/draw.d.ts +154 -75
  112. package/src/esm/draw.js +304 -135
  113. package/src/esm/draw.js.map +1 -1
  114. package/src/esm/drawgl.d.ts +87 -50
  115. package/src/esm/drawgl.js +86 -31
  116. package/src/esm/drawgl.js.map +1 -1
  117. package/src/esm/drawutilssvg.d.ts +226 -53
  118. package/src/esm/drawutilssvg.js +369 -92
  119. package/src/esm/drawutilssvg.js.map +1 -1
  120. package/src/esm/interfaces/DrawLib.d.ts +157 -79
  121. package/src/esm/interfaces/DrawLib.js +6 -0
  122. package/src/esm/interfaces/DrawLib.js.map +1 -1
  123. package/src/esm/interfaces/core.d.ts +13 -2
  124. package/src/esm/interfaces/core.js +1 -0
  125. package/src/esm/interfaces/core.js.map +1 -1
  126. package/src/esm/utils/Params.d.ts +15 -0
  127. package/src/esm/utils/Params.js +44 -0
  128. package/src/esm/utils/Params.js.map +1 -0
  129. package/src/esm/utils/algorithms/ContourLineDetection.d.ts +150 -0
  130. package/src/esm/utils/algorithms/ContourLineDetection.js +362 -0
  131. package/src/esm/utils/algorithms/ContourLineDetection.js.map +1 -0
  132. package/src/esm/utils/algorithms/clearDuplicateVertices.d.ts +21 -0
  133. package/src/esm/utils/algorithms/clearDuplicateVertices.js +44 -0
  134. package/src/esm/utils/algorithms/clearDuplicateVertices.js.map +1 -0
  135. package/src/esm/utils/datastructures/DataGrid2d.d.ts +47 -0
  136. package/src/esm/utils/datastructures/DataGrid2d.js +19 -0
  137. package/src/esm/utils/datastructures/DataGrid2d.js.map +1 -0
  138. package/src/esm/utils/datastructures/DataGrid2dListAdapter.d.ts +65 -0
  139. package/src/esm/utils/datastructures/DataGrid2dListAdapter.js +79 -0
  140. package/src/esm/utils/datastructures/DataGrid2dListAdapter.js.map +1 -0
  141. package/src/esm/utils/datastructures/GenericPath.d.ts +14 -3
  142. package/src/esm/utils/datastructures/GenericPath.js +20 -3
  143. package/src/esm/utils/datastructures/GenericPath.js.map +1 -1
  144. package/src/esm/utils/detectDarkMode.d.ts +10 -0
  145. package/src/esm/utils/detectDarkMode.js +28 -0
  146. package/src/esm/utils/detectDarkMode.js.map +1 -0
  147. package/src/ts/BezierPath.ts +72 -241
  148. package/src/ts/Bounds.ts +25 -1
  149. package/src/ts/CubicBezierCurve.ts +139 -12
  150. package/src/ts/Line.ts +2 -1
  151. package/src/ts/PBText.ts +10 -9
  152. package/src/ts/PlotBoilerplate.ts +56 -19
  153. package/src/ts/Polygon.ts +121 -1
  154. package/src/ts/VEllipse.ts +2 -2
  155. package/src/ts/Vector.ts +4 -4
  156. package/src/ts/VertTuple.ts +4 -3
  157. package/src/ts/Vertex.ts +20 -4
  158. package/src/ts/draw.ts +311 -115
  159. package/src/ts/drawgl.ts +133 -71
  160. package/src/ts/drawutilssvg.ts +543 -121
  161. package/src/ts/interfaces/DrawLib.ts +219 -83
  162. package/src/ts/interfaces/core.ts +14 -2
  163. package/src/ts/utils/Params.ts +47 -0
  164. package/src/ts/utils/algorithms/ContourLineDetection.ts +485 -0
  165. package/src/ts/utils/algorithms/clearDuplicateVertices.ts +49 -0
  166. package/src/ts/utils/datastructures/DataGrid2d.ts +54 -0
  167. package/src/ts/utils/datastructures/DataGrid2dListAdapter.ts +121 -0
  168. package/src/ts/utils/datastructures/GenericPath.ts +21 -3
  169. package/src/ts/utils/detectDarkMode.ts +30 -0
@@ -0,0 +1,150 @@
1
+ /**
2
+ * A function to detect contour lines from 3D terrain data.
3
+ *
4
+ * For usage see demo `./demos/48-contour-plot`.
5
+ *
6
+ * @requires detectPaths
7
+ * @requires GenericPath
8
+ * @author Ikaros Kappler
9
+ * @date 2023-11-05
10
+ * @modified 2023-11-20 Addig path detection on a triangle based grid.
11
+ * @version 1.0.0
12
+ */
13
+ import { Line } from "../../Line";
14
+ import { IDataGrid2d } from "../datastructures/DataGrid2d";
15
+ import { GenericPath } from "../datastructures/GenericPath";
16
+ export declare class ContourLineDetection {
17
+ private dataGrid;
18
+ private rawLinearPathSegments;
19
+ static CLOSE_GAP_TYPE_NONE: number;
20
+ static CLOSE_GAP_TYPE_ABOVE: number;
21
+ static CLOSE_GAP_TYPE_BELOW: number;
22
+ debugMode: boolean;
23
+ /**
24
+ * Creates a new instance for calculating contour lines from the given data grid.
25
+ * @param {IDataGrid2d<number>} dataGrid - The data grid to use. Must not contain any NaN or null values.
26
+ * @param {boolean=?} debugMode - (optional) Pass `true` to log warnings on (rare) critical edge cases where the algorithm might fail.
27
+ */
28
+ constructor(dataGrid: IDataGrid2d<number>, debugMode?: boolean);
29
+ /**
30
+ * Detect contour paths from the underlying data source.
31
+ *
32
+ * @param {number} criticalHeightValue - The height value. If above data's maximum or below data's minimum then the result will be empty (no intersections).
33
+ * @param {number} options.closeGapType - `CLOSE_GAP_TYPE_NONE` or `CLOSE_GAP_TYPE_ABOVE` or `CLOSE_GAP_TYPE_BELOW`.
34
+ * @param {boolean=false} options.useTriangles - If set to true the detection will split each face3 quad into two triangle faces.
35
+ * @param {pathDetectEpsilon=0.000001} options.pathDetectEpsilon - (optional) The epsilon to tell if two points are located 'in the same place'. Used for connected path detection. If not specified the value `0.0000001` is used.
36
+ * @param {pointEliminationEpsilon=0.0000001} options.pointEliminationEpsilon - (optional) The epsilon for duplicate point elimination (default is 0.000001).
37
+ * @param {function?} onRawSegmentsDetected - (optional) Get the interim result of all detected single lines before path detection starts; DO NOT MODIFY the array.
38
+ * @returns {Array<GenericPath>} - A list of connected paths that resemble the contour lines of the data/terrain at the given height value.
39
+ */
40
+ detectContourPaths(criticalHeightValue: number, options?: {
41
+ closeGapType: number;
42
+ useTriangles?: boolean;
43
+ pointEliminationEpsilon?: number;
44
+ pathDetectEpsilon?: number;
45
+ onRawSegmentsDetected?: (rawSegmentsDoNotModifiy: Array<Line>) => void;
46
+ }): Array<GenericPath>;
47
+ /**
48
+ * This function will calculate a single intersecion line of the given face4 data
49
+ * segment. If the given face does not intersect with the plane at the given `heightValue`
50
+ * then no segments will be stored.
51
+ *
52
+ * @param {number} xIndex - The x position (index) of the data face.
53
+ * @param {number} yIndex - The y position (index) of the data face.
54
+ * @param {[[number,number],[number,number]]} heightFace - The data sample that composes the face4 as a two-dimensional number array.
55
+ * @param {number} heightValue - The height value of the intersection plane to check for.
56
+ * @returns {Line|null}
57
+ */
58
+ private findHeight4FaceIntersectionLine;
59
+ /**
60
+ * This function will calculate a single intersecion line of the given face4 data
61
+ * segment. If the given face does not intersect with the plane at the given `heightValue`
62
+ * then no segments will be stored.
63
+ *
64
+ * @param {number} xIndex - The x position (index) of the data face.
65
+ * @param {number} yIndex - The y position (index) of the data face.
66
+ * @param {[[number,number],[number,number]]} heightFace - The data sample that composes the face4 as a two-dimensional number array.
67
+ * @param {number} heightValue - The height value of the intersection plane to check for.
68
+ * @returns {Line|null}
69
+ */
70
+ private findHeightFaceIntersectionLines;
71
+ /**
72
+ * This function will calculate a single intersecion line of the given face3 data
73
+ * segment. If the given face does not intersect with the plane at the given `heightValue`
74
+ * then no segments will be stored.
75
+ *
76
+ * @param {number} xIndexA - The x position (index) of the first triangle data point.
77
+ * @param {number} yIndexA - The y position (index) of the first triangle data point.
78
+ * @param {[[number,number],[number,number]]} heightFace - The data sample that composes the face4 as a two-dimensional number array.
79
+ * @param {number} heightValue - The height value of the intersection plane to check for.
80
+ * @returns {Line|null}
81
+ */
82
+ private findHeighteFace3IntersectionLine;
83
+ /**
84
+ * This procedure will look at the face4 at the ((x,y),(nextX,nextY)) position – which are four values –
85
+ * and determines the local contour lines for these cases.
86
+ *
87
+ * This is used to detect and calculate edge cases on the borders of the underliying height data:
88
+ * * left and right border (x=0, x=data.xSegmentCount)
89
+ * * top and bottom border (x=y, x=data.ySegmentCount)
90
+ *
91
+ * Resulting path segments will be stored in the global `rawLinearPathSegments` array for further processing.
92
+ *
93
+ * @param {number} x
94
+ * @param {number} y
95
+ * @param {number} nextX
96
+ * @param {number} nextY
97
+ * @param {number} criticalHeightValue
98
+ * @param {number} closeGapType - CLOSE_GAP_TYPE_ABOVE or CLOSE_GAP_TYPE_BELOW.
99
+ * @return {void}
100
+ */
101
+ detectAboveBelowLerpSegment(x: number, y: number, nextX: number, nextY: number, criticalHeightValue: number, closeGapType: number): void;
102
+ /**
103
+ * Checks if both value are on the same side of the critical value (above or below). The `closeGapType`
104
+ * indictes if `CLOSE_GAP_TYPE_BELOW` or `CLOSE_GAP_TYPE_ABOVE` should be used as a rule.
105
+ *
106
+ * @param {number} valueA
107
+ * @param {number} valueB
108
+ * @param {number} criticalValue
109
+ * @param {number} closeGapType
110
+ * @returns {boolean}
111
+ */
112
+ private areBothValuesOnRequiredPlaneSide;
113
+ /**
114
+ * Test if a given numeric value (`curValue`) is between the given values `valA` and `valB`.
115
+ * Value A and B don't need to be in ascending order, so `valA <= curValue <= valB` and `valB <= curvalue <= valA`
116
+ * will do the job.
117
+ *
118
+ * @param {number} valA - The first of the two bounds.
119
+ * @param {number} valB - The second of the two bounds.
120
+ * @param {number} curValue - The value to check if it is between (or equal) to the given bounds.
121
+ * @returns {boolean}
122
+ */
123
+ private isBetween;
124
+ /**
125
+ * Get a 'lerp' value - which is some sort of percentage/ratio for the `curValue` inside the
126
+ * range of the given interval `[valA ... valB]`.
127
+ *
128
+ * Examples:
129
+ * * getLerpRatio(0,100,50) === 0.5
130
+ * * getLerpRatio(50,100,75) === 0.5
131
+ * * getLerpRatio(0,100,0) === 0.0
132
+ * * getLerpRatio(0,100,100) === 1.0
133
+ * * getLerpRatio(0,100,-50) === -0.5
134
+ *
135
+ * @param {number} valA
136
+ * @param {number} valB
137
+ * @param {number} curValue
138
+ * @returns
139
+ */
140
+ private getLerpRatio;
141
+ /**
142
+ * Helper function to lerp a numeric value.
143
+ *
144
+ * @param {number} min - The min (start) value. Doesn't necesarily need to be the smaller one.
145
+ * @param {number} max - The max (end) value. Doesn't necesarily need to be the larger one.
146
+ * @param {number} ratio - The lerp ratio; usually a value between 0.0 and 1.0, but other values a valid for linear interpolation, too.
147
+ * @returns {number}
148
+ */
149
+ private lerp;
150
+ }
@@ -0,0 +1,367 @@
1
+ "use strict";
2
+ /**
3
+ * A function to detect contour lines from 3D terrain data.
4
+ *
5
+ * For usage see demo `./demos/48-contour-plot`.
6
+ *
7
+ * @requires detectPaths
8
+ * @requires GenericPath
9
+ * @author Ikaros Kappler
10
+ * @date 2023-11-05
11
+ * @modified 2023-11-20 Addig path detection on a triangle based grid.
12
+ * @version 1.0.0
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ContourLineDetection = void 0;
16
+ var Line_1 = require("../../Line");
17
+ var Vertex_1 = require("../../Vertex");
18
+ var detectPaths_1 = require("./detectPaths");
19
+ var clearDuplicateVertices_1 = require("./clearDuplicateVertices");
20
+ var ContourLineDetection = /** @class */ (function () {
21
+ /**
22
+ * Creates a new instance for calculating contour lines from the given data grid.
23
+ * @param {IDataGrid2d<number>} dataGrid - The data grid to use. Must not contain any NaN or null values.
24
+ * @param {boolean=?} debugMode - (optional) Pass `true` to log warnings on (rare) critical edge cases where the algorithm might fail.
25
+ */
26
+ function ContourLineDetection(dataGrid, debugMode) {
27
+ this.rawLinearPathSegments = [];
28
+ // Activates/deactivates warning messages on rare edge cases where local path detection fails.
29
+ this.debugMode = false;
30
+ this.dataGrid = dataGrid;
31
+ this.debugMode = Boolean(debugMode);
32
+ }
33
+ /**
34
+ * Detect contour paths from the underlying data source.
35
+ *
36
+ * @param {number} criticalHeightValue - The height value. If above data's maximum or below data's minimum then the result will be empty (no intersections).
37
+ * @param {number} options.closeGapType - `CLOSE_GAP_TYPE_NONE` or `CLOSE_GAP_TYPE_ABOVE` or `CLOSE_GAP_TYPE_BELOW`.
38
+ * @param {boolean=false} options.useTriangles - If set to true the detection will split each face3 quad into two triangle faces.
39
+ * @param {pathDetectEpsilon=0.000001} options.pathDetectEpsilon - (optional) The epsilon to tell if two points are located 'in the same place'. Used for connected path detection. If not specified the value `0.0000001` is used.
40
+ * @param {pointEliminationEpsilon=0.0000001} options.pointEliminationEpsilon - (optional) The epsilon for duplicate point elimination (default is 0.000001).
41
+ * @param {function?} onRawSegmentsDetected - (optional) Get the interim result of all detected single lines before path detection starts; DO NOT MODIFY the array.
42
+ * @returns {Array<GenericPath>} - A list of connected paths that resemble the contour lines of the data/terrain at the given height value.
43
+ */
44
+ ContourLineDetection.prototype.detectContourPaths = function (criticalHeightValue, options) {
45
+ var _a, _b;
46
+ options = options || { closeGapType: ContourLineDetection.CLOSE_GAP_TYPE_NONE };
47
+ // First: clear the buffer
48
+ this.rawLinearPathSegments = [];
49
+ // Imagine a face4 element like this
50
+ // (x,y) (x+1,y)
51
+ // A-----B
52
+ // | / |
53
+ // | / |
54
+ // D-----C
55
+ // (x,y+1) (x+1,y+1)
56
+ // then result in the buffer will be
57
+ // [ [A,B],
58
+ // [D,C] ]
59
+ // Note that the diagonal line (used for triangles) is optional; depends on `options.useTriangles`.
60
+ var heightFace = [
61
+ [0, 0],
62
+ [0, 0]
63
+ ];
64
+ for (var y = 0; y + 1 < this.dataGrid.ySegmentCount; y++) {
65
+ for (var x = 0; x + 1 < this.dataGrid.xSegmentCount; x++) {
66
+ this.dataGrid.getDataFace4At(x, y, heightFace);
67
+ this.findHeightFaceIntersectionLines(x, y, heightFace, criticalHeightValue, (_a = options.pointEliminationEpsilon) !== null && _a !== void 0 ? _a : 0.0000001, options.useTriangles);
68
+ }
69
+ }
70
+ // Collect value above/below on the y axis
71
+ if (options.closeGapType == ContourLineDetection.CLOSE_GAP_TYPE_ABOVE ||
72
+ options.closeGapType == ContourLineDetection.CLOSE_GAP_TYPE_BELOW) {
73
+ var xExtremes = [0, this.dataGrid.xSegmentCount - 1];
74
+ for (var i = 0; i < xExtremes.length; i++) {
75
+ var x_1 = xExtremes[i];
76
+ for (var y = 0; y + 1 < this.dataGrid.ySegmentCount; y++) {
77
+ var nextX = x_1;
78
+ var nextY = y + 1;
79
+ this.detectAboveBelowLerpSegment(x_1, y, nextX, nextY, criticalHeightValue, options.closeGapType);
80
+ }
81
+ }
82
+ var yExtremes = [0, this.dataGrid.ySegmentCount - 1];
83
+ for (var j = 0; j < yExtremes.length; j++) {
84
+ var y = yExtremes[j];
85
+ for (var x = 0; x + 1 < this.dataGrid.xSegmentCount; x++) {
86
+ var nextX = x + 1;
87
+ var nextY = y;
88
+ this.detectAboveBelowLerpSegment(x, y, nextX, nextY, criticalHeightValue, options.closeGapType);
89
+ }
90
+ }
91
+ }
92
+ if (options.onRawSegmentsDetected) {
93
+ options.onRawSegmentsDetected(this.rawLinearPathSegments);
94
+ }
95
+ // Detect connected paths
96
+ var pathSegments = detectPaths_1.detectPaths(this.rawLinearPathSegments, (_b = options.pathDetectEpsilon) !== null && _b !== void 0 ? _b : 0.0000001); // Epsilon
97
+ // Filter out segments with only a single line of length~=0
98
+ pathSegments = pathSegments.filter(function (pathSegment) {
99
+ return (pathSegment.segments.length != 1 ||
100
+ (pathSegment.segments.length === 1 && pathSegment.segments[0].length() > 0.1));
101
+ });
102
+ return pathSegments;
103
+ };
104
+ /**
105
+ * This function will calculate a single intersecion line of the given face4 data
106
+ * segment. If the given face does not intersect with the plane at the given `heightValue`
107
+ * then no segments will be stored.
108
+ *
109
+ * @param {number} xIndex - The x position (index) of the data face.
110
+ * @param {number} yIndex - The y position (index) of the data face.
111
+ * @param {[[number,number],[number,number]]} heightFace - The data sample that composes the face4 as a two-dimensional number array.
112
+ * @param {number} heightValue - The height value of the intersection plane to check for.
113
+ * @returns {Line|null}
114
+ */
115
+ ContourLineDetection.prototype.findHeight4FaceIntersectionLine = function (xIndex, yIndex, heightFace, heightValue, pointEliminationEpsilon) {
116
+ var heightValueA = heightFace[0][0]; // value at (x,y)
117
+ var heightValueB = heightFace[1][0];
118
+ var heightValueC = heightFace[1][1];
119
+ var heightValueD = heightFace[0][1];
120
+ if (heightValueA === null || heightValueB === null || heightValueC === null || heightValueD === null) {
121
+ throw "[findHeightFace4IntersectionLine] Cannot extract data face at (" + xIndex + "," + yIndex + "). Some values are null.";
122
+ }
123
+ var points = [];
124
+ // Case A: use full quad face
125
+ if (this.isBetween(heightValueA, heightValueB, heightValue)) {
126
+ var lerpValueByHeight = this.getLerpRatio(heightValueA, heightValueB, heightValue);
127
+ points.push(new Vertex_1.Vertex(this.lerp(xIndex, xIndex + 1, lerpValueByHeight), yIndex));
128
+ }
129
+ if (this.isBetween(heightValueB, heightValueC, heightValue)) {
130
+ var lerpValueByHeight = this.getLerpRatio(heightValueB, heightValueC, heightValue);
131
+ points.push(new Vertex_1.Vertex(xIndex + 1, this.lerp(yIndex, yIndex + 1, lerpValueByHeight)));
132
+ }
133
+ if (this.isBetween(heightValueC, heightValueD, heightValue)) {
134
+ var lerpValueByHeight = this.getLerpRatio(heightValueC, heightValueD, heightValue);
135
+ points.push(new Vertex_1.Vertex(this.lerp(xIndex + 1, xIndex, lerpValueByHeight), yIndex + 1));
136
+ }
137
+ if (this.isBetween(heightValueD, heightValueA, heightValue)) {
138
+ var lerpValueByHeight = this.getLerpRatio(heightValueD, heightValueA, heightValue);
139
+ points.push(new Vertex_1.Vertex(xIndex, this.lerp(yIndex + 1, yIndex, lerpValueByHeight)));
140
+ }
141
+ // Warning: if a plane intersection point is located EXACTLY on the corner
142
+ // edge of a face, then the two adjacent edges will result in 2x the same
143
+ // intersecion point. This must be handled as one, so filter the point list
144
+ // by an epsilon.
145
+ points = clearDuplicateVertices_1.clearDuplicateVertices(points, pointEliminationEpsilon); // 0.000001);
146
+ if (points.length >= 2) {
147
+ var startPoint = points[0];
148
+ var endPoint = points[1];
149
+ if (this.debugMode && points.length > 2) {
150
+ console.warn("[findHeightFace4IntersectionLine] Detected more than 2 points on one face whre only 0 or 2 should appear. At ", xIndex, yIndex, points);
151
+ }
152
+ return new Line_1.Line(startPoint, endPoint);
153
+ }
154
+ else {
155
+ if (this.debugMode && points.length === 1) {
156
+ console.warn("[findHeightFace4IntersectionLine] Point list has only one point (should not happen).");
157
+ }
158
+ return null;
159
+ }
160
+ };
161
+ /**
162
+ * This function will calculate a single intersecion line of the given face4 data
163
+ * segment. If the given face does not intersect with the plane at the given `heightValue`
164
+ * then no segments will be stored.
165
+ *
166
+ * @param {number} xIndex - The x position (index) of the data face.
167
+ * @param {number} yIndex - The y position (index) of the data face.
168
+ * @param {[[number,number],[number,number]]} heightFace - The data sample that composes the face4 as a two-dimensional number array.
169
+ * @param {number} heightValue - The height value of the intersection plane to check for.
170
+ * @returns {Line|null}
171
+ */
172
+ ContourLineDetection.prototype.findHeightFaceIntersectionLines = function (xIndex, yIndex, heightFace, criticalHeightValue, pointEliminationEpsilon, useTriangles) {
173
+ // Imagine a face4 element like this
174
+ // (x,y) (x+1,y)
175
+ // A-----B
176
+ // | / |
177
+ // | / |
178
+ // D-----C
179
+ // (x,y+1) (x+1,y+1)
180
+ // then result in the buffer will be
181
+ // [ [A,B],
182
+ // [D,C] ]
183
+ if (useTriangles) {
184
+ var lineA = this.findHeighteFace3IntersectionLine(xIndex, yIndex, xIndex, yIndex + 1, xIndex + 1, yIndex, [heightFace[0][0], heightFace[0][1], heightFace[1][0]], criticalHeightValue, pointEliminationEpsilon);
185
+ if (lineA) {
186
+ this.rawLinearPathSegments.push(lineA);
187
+ }
188
+ var lineB = this.findHeighteFace3IntersectionLine(xIndex, yIndex + 1, xIndex + 1, yIndex + 1, xIndex + 1, yIndex, [heightFace[0][1], heightFace[1][1], heightFace[1][0]], criticalHeightValue, pointEliminationEpsilon);
189
+ if (lineB) {
190
+ this.rawLinearPathSegments.push(lineB);
191
+ }
192
+ }
193
+ else {
194
+ var line = this.findHeight4FaceIntersectionLine(xIndex, yIndex, heightFace, criticalHeightValue, pointEliminationEpsilon);
195
+ if (line) {
196
+ this.rawLinearPathSegments.push(line);
197
+ }
198
+ }
199
+ };
200
+ /**
201
+ * This function will calculate a single intersecion line of the given face3 data
202
+ * segment. If the given face does not intersect with the plane at the given `heightValue`
203
+ * then no segments will be stored.
204
+ *
205
+ * @param {number} xIndexA - The x position (index) of the first triangle data point.
206
+ * @param {number} yIndexA - The y position (index) of the first triangle data point.
207
+ * @param {[[number,number],[number,number]]} heightFace - The data sample that composes the face4 as a two-dimensional number array.
208
+ * @param {number} heightValue - The height value of the intersection plane to check for.
209
+ * @returns {Line|null}
210
+ */
211
+ ContourLineDetection.prototype.findHeighteFace3IntersectionLine = function (xIndexA, yIndexA, xIndexB, yIndexB, xIndexC, yIndexC, heightFace, heightValue, pointEliminationEpsilon) {
212
+ var heightValueA = heightFace[0]; // value at (x,y)
213
+ var heightValueB = heightFace[1];
214
+ var heightValueC = heightFace[2];
215
+ if (heightValueA === null || heightValueB === null || heightValueC === null) {
216
+ throw "[findHeightFace3IntersectionLine] Cannot extract data face at (" + xIndexA + "," + yIndexA + "). Some values are null.";
217
+ }
218
+ var points = [];
219
+ // Case A: use full quad face
220
+ if (this.isBetween(heightValueA, heightValueB, heightValue)) {
221
+ var lerpValueByHeight = this.getLerpRatio(heightValueA, heightValueB, heightValue);
222
+ points.push(new Vertex_1.Vertex(this.lerp(xIndexA, xIndexB, lerpValueByHeight), this.lerp(yIndexA, yIndexB, lerpValueByHeight)));
223
+ }
224
+ if (this.isBetween(heightValueB, heightValueC, heightValue)) {
225
+ var lerpValueByHeight = this.getLerpRatio(heightValueB, heightValueC, heightValue);
226
+ // points.push(new Vertex(xIndex + 1, this.lerp(yIndex, yIndex + 1, lerpValueByHeight)));
227
+ points.push(new Vertex_1.Vertex(this.lerp(xIndexB, xIndexC, lerpValueByHeight), this.lerp(yIndexB, yIndexC, lerpValueByHeight)));
228
+ }
229
+ if (this.isBetween(heightValueC, heightValueA, heightValue)) {
230
+ var lerpValueByHeight = this.getLerpRatio(heightValueC, heightValueA, heightValue);
231
+ // points.push(new Vertex(this.lerp(xIndex + 1, xIndex, lerpValueByHeight), yIndex + 1));
232
+ points.push(new Vertex_1.Vertex(this.lerp(xIndexC, xIndexA, lerpValueByHeight), this.lerp(yIndexC, yIndexA, lerpValueByHeight)));
233
+ }
234
+ // Warning: if a plane intersection point is located EXACTLY on the corner
235
+ // edge of a face, then the two adjacent edges will result in 2x the same
236
+ // intersecion point. This must be handled as one, so filter the point list
237
+ // by an epsilon.
238
+ points = clearDuplicateVertices_1.clearDuplicateVertices(points, pointEliminationEpsilon); // 0.0000001);
239
+ if (points.length >= 2) {
240
+ var startPoint = points[0];
241
+ var endPoint = points[1];
242
+ if (this.debugMode && points.length > 2) {
243
+ console.warn("[findHeightFace3IntersectionLine] Detected more than 2 points on one face whre only 0 or 2 should appear. At ", xIndexA, yIndexA, points);
244
+ }
245
+ return new Line_1.Line(startPoint, endPoint);
246
+ }
247
+ else {
248
+ if (this.debugMode && points.length === 1) {
249
+ console.warn("[findHeightFace3IntersectionLine] Point list has only one point (should not happen).");
250
+ }
251
+ return null;
252
+ }
253
+ };
254
+ /**
255
+ * This procedure will look at the face4 at the ((x,y),(nextX,nextY)) position – which are four values –
256
+ * and determines the local contour lines for these cases.
257
+ *
258
+ * This is used to detect and calculate edge cases on the borders of the underliying height data:
259
+ * * left and right border (x=0, x=data.xSegmentCount)
260
+ * * top and bottom border (x=y, x=data.ySegmentCount)
261
+ *
262
+ * Resulting path segments will be stored in the global `rawLinearPathSegments` array for further processing.
263
+ *
264
+ * @param {number} x
265
+ * @param {number} y
266
+ * @param {number} nextX
267
+ * @param {number} nextY
268
+ * @param {number} criticalHeightValue
269
+ * @param {number} closeGapType - CLOSE_GAP_TYPE_ABOVE or CLOSE_GAP_TYPE_BELOW.
270
+ * @return {void}
271
+ */
272
+ ContourLineDetection.prototype.detectAboveBelowLerpSegment = function (x, y, nextX, nextY, criticalHeightValue, closeGapType) {
273
+ var heightValueA = this.dataGrid.getDataValueAt(x, y);
274
+ var heightValueB = this.dataGrid.getDataValueAt(nextX, nextY);
275
+ // if (heightValueA >= criticalHeightValue && heightValueB >= criticalHeightValue) {
276
+ if (this.areBothValuesOnRequiredPlaneSide(heightValueA, heightValueB, criticalHeightValue, closeGapType)) {
277
+ // Both above
278
+ var line = new Line_1.Line(new Vertex_1.Vertex(x, y), new Vertex_1.Vertex(nextX, nextY));
279
+ this.rawLinearPathSegments.push(line);
280
+ }
281
+ else if ((closeGapType == ContourLineDetection.CLOSE_GAP_TYPE_ABOVE &&
282
+ heightValueA >= criticalHeightValue &&
283
+ heightValueB <= criticalHeightValue) ||
284
+ (closeGapType == ContourLineDetection.CLOSE_GAP_TYPE_BELOW &&
285
+ heightValueA <= criticalHeightValue &&
286
+ heightValueB >= criticalHeightValue)) {
287
+ // Only one of both (first) is above -> interpolate to find exact intersection point
288
+ var lerpValueByHeight = this.getLerpRatio(heightValueA, heightValueB, criticalHeightValue);
289
+ var interpLine = new Line_1.Line(new Vertex_1.Vertex(x, y), new Vertex_1.Vertex(this.lerp(x, nextX, lerpValueByHeight), this.lerp(y, nextY, lerpValueByHeight)));
290
+ this.rawLinearPathSegments.push(interpLine);
291
+ }
292
+ else if ((closeGapType == ContourLineDetection.CLOSE_GAP_TYPE_ABOVE &&
293
+ heightValueA <= criticalHeightValue &&
294
+ heightValueB >= criticalHeightValue) ||
295
+ (closeGapType == ContourLineDetection.CLOSE_GAP_TYPE_BELOW &&
296
+ heightValueA >= criticalHeightValue &&
297
+ heightValueB <= criticalHeightValue)) {
298
+ // Only one of both (second) is above -> interpolate to find exact intersection point
299
+ var lerpValueByHeight = this.getLerpRatio(heightValueA, heightValueB, criticalHeightValue);
300
+ var interpLine = new Line_1.Line(new Vertex_1.Vertex(this.lerp(x, nextX, lerpValueByHeight), this.lerp(y, nextY, lerpValueByHeight)), new Vertex_1.Vertex(nextX, nextY));
301
+ this.rawLinearPathSegments.push(interpLine);
302
+ }
303
+ };
304
+ /**
305
+ * Checks if both value are on the same side of the critical value (above or below). The `closeGapType`
306
+ * indictes if `CLOSE_GAP_TYPE_BELOW` or `CLOSE_GAP_TYPE_ABOVE` should be used as a rule.
307
+ *
308
+ * @param {number} valueA
309
+ * @param {number} valueB
310
+ * @param {number} criticalValue
311
+ * @param {number} closeGapType
312
+ * @returns {boolean}
313
+ */
314
+ ContourLineDetection.prototype.areBothValuesOnRequiredPlaneSide = function (valueA, valueB, criticalValue, closeGapType) {
315
+ return ((closeGapType == ContourLineDetection.CLOSE_GAP_TYPE_BELOW && valueA <= criticalValue && valueB <= criticalValue) ||
316
+ (closeGapType == ContourLineDetection.CLOSE_GAP_TYPE_ABOVE && valueA >= criticalValue && valueB >= criticalValue));
317
+ };
318
+ /**
319
+ * Test if a given numeric value (`curValue`) is between the given values `valA` and `valB`.
320
+ * Value A and B don't need to be in ascending order, so `valA <= curValue <= valB` and `valB <= curvalue <= valA`
321
+ * will do the job.
322
+ *
323
+ * @param {number} valA - The first of the two bounds.
324
+ * @param {number} valB - The second of the two bounds.
325
+ * @param {number} curValue - The value to check if it is between (or equal) to the given bounds.
326
+ * @returns {boolean}
327
+ */
328
+ ContourLineDetection.prototype.isBetween = function (valA, valB, curValue) {
329
+ return (valA <= curValue && curValue <= valB) || (valB <= curValue && curValue <= valA);
330
+ };
331
+ /**
332
+ * Get a 'lerp' value - which is some sort of percentage/ratio for the `curValue` inside the
333
+ * range of the given interval `[valA ... valB]`.
334
+ *
335
+ * Examples:
336
+ * * getLerpRatio(0,100,50) === 0.5
337
+ * * getLerpRatio(50,100,75) === 0.5
338
+ * * getLerpRatio(0,100,0) === 0.0
339
+ * * getLerpRatio(0,100,100) === 1.0
340
+ * * getLerpRatio(0,100,-50) === -0.5
341
+ *
342
+ * @param {number} valA
343
+ * @param {number} valB
344
+ * @param {number} curValue
345
+ * @returns
346
+ */
347
+ ContourLineDetection.prototype.getLerpRatio = function (valA, valB, curValue) {
348
+ return (curValue - valA) / (valB - valA);
349
+ };
350
+ /**
351
+ * Helper function to lerp a numeric value.
352
+ *
353
+ * @param {number} min - The min (start) value. Doesn't necesarily need to be the smaller one.
354
+ * @param {number} max - The max (end) value. Doesn't necesarily need to be the larger one.
355
+ * @param {number} ratio - The lerp ratio; usually a value between 0.0 and 1.0, but other values a valid for linear interpolation, too.
356
+ * @returns {number}
357
+ */
358
+ ContourLineDetection.prototype.lerp = function (min, max, ratio) {
359
+ return min + (max - min) * ratio;
360
+ };
361
+ ContourLineDetection.CLOSE_GAP_TYPE_NONE = 0;
362
+ ContourLineDetection.CLOSE_GAP_TYPE_ABOVE = 1;
363
+ ContourLineDetection.CLOSE_GAP_TYPE_BELOW = 2;
364
+ return ContourLineDetection;
365
+ }());
366
+ exports.ContourLineDetection = ContourLineDetection;
367
+ //# sourceMappingURL=ContourLineDetection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContourLineDetection.js","sourceRoot":"","sources":["../../../ts/utils/algorithms/ContourLineDetection.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAEH,mCAAkC;AAClC,uCAAsC;AAEtC,6CAA4C;AAC5C,mEAAkE;AAQlE;IAYE;;;;OAIG;IACH,8BAAY,QAA6B,EAAE,SAAmB;QAdtD,0BAAqB,GAAgB,EAAE,CAAC;QAMhD,8FAA8F;QACvF,cAAS,GAAY,KAAK,CAAC;QAQhC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAED;;;;;;;;;;OAUG;IACH,iDAAkB,GAAlB,UACE,mBAA2B,EAC3B,OAMC;;QAED,OAAO,GAAG,OAAO,IAAI,EAAE,YAAY,EAAE,oBAAoB,CAAC,mBAAmB,EAAE,CAAC;QAEhF,0BAA0B;QAC1B,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC;QAEhC,oCAAoC;QACpC,yBAAyB;QACzB,kBAAkB;QAClB,kBAAkB;QAClB,kBAAkB;QAClB,kBAAkB;QAClB,4BAA4B;QAC5B,uCAAuC;QACvC,aAAa;QACb,cAAc;QACd,mGAAmG;QACnG,IAAM,UAAU,GAA0B;YACxC,CAAC,CAAC,EAAE,CAAC,CAAC;YACN,CAAC,CAAC,EAAE,CAAC,CAAC;SACP,CAAC;QACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,EAAE,EAAE;YACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,EAAE,EAAE;gBACxD,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;gBAC/C,IAAI,CAAC,+BAA+B,CAClC,CAAC,EACD,CAAC,EACD,UAAU,EACV,mBAAmB,QACnB,OAAO,CAAC,uBAAuB,mCAAI,SAAS,EAC5C,OAAO,CAAC,YAAY,CACrB,CAAC;aACH;SACF;QAED,0CAA0C;QAC1C,IACE,OAAO,CAAC,YAAY,IAAI,oBAAoB,CAAC,oBAAoB;YACjE,OAAO,CAAC,YAAY,IAAI,oBAAoB,CAAC,oBAAoB,EACjE;YACA,IAAM,SAAS,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;YACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACzC,IAAM,GAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;gBACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,EAAE,EAAE;oBACxD,IAAM,KAAK,GAAG,GAAC,CAAC;oBAChB,IAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;oBACpB,IAAI,CAAC,2BAA2B,CAAC,GAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;iBACjG;aACF;YACD,IAAM,SAAS,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;YACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACzC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;gBACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,EAAE,EAAE;oBACxD,IAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;oBACpB,IAAM,KAAK,GAAG,CAAC,CAAC;oBAChB,IAAI,CAAC,2BAA2B,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;iBACjG;aACF;SACF;QAED,IAAI,OAAO,CAAC,qBAAqB,EAAE;YACjC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;SAC3D;QAED,yBAAyB;QACzB,IAAI,YAAY,GAAuB,yBAAW,CAAC,IAAI,CAAC,qBAAqB,QAAE,OAAO,CAAC,iBAAiB,mCAAI,SAAS,CAAC,CAAC,CAAC,UAAU;QAClI,2DAA2D;QAC3D,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,UAAU,WAAW;YACtD,OAAO,CACL,WAAW,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC;gBAChC,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAK,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAU,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CACxF,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;;;;;;;;;OAUG;IACK,8DAA+B,GAAvC,UACE,MAAc,EACd,MAAc,EACd,UAAiC,EACjC,WAAmB,EACnB,uBAA+B;QAE/B,IAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB;QACxD,IAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,IAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,IAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEtC,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,IAAI,EAAE;YACpG,MAAM,oEAAkE,MAAM,SAAI,MAAM,6BAA0B,CAAC;SACpH;QAED,IAAI,MAAM,GAAkB,EAAE,CAAC;QAE/B,6BAA6B;QAC7B,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAC3D,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,IAAI,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;SACnF;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAC3D,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,IAAI,eAAM,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;SACvF;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAC3D,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,IAAI,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;SACvF;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAC3D,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,IAAI,eAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;SACnF;QAED,0EAA0E;QAC1E,yEAAyE;QACzE,2EAA2E;QAC3E,iBAAiB;QACjB,MAAM,GAAG,+CAAsB,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,CAAC,aAAa;QAE/E,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;YACtB,IAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7B,IAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;gBACvC,OAAO,CAAC,IAAI,CACV,+GAA+G,EAC/G,MAAM,EACN,MAAM,EACN,MAAM,CACP,CAAC;aACH;YACD,OAAO,IAAI,WAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;SACvC;aAAM;YACL,IAAI,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;gBACzC,OAAO,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;aACtG;YACD,OAAO,IAAI,CAAC;SACb;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACK,8DAA+B,GAAvC,UACE,MAAc,EACd,MAAc,EACd,UAAiC,EACjC,mBAA2B,EAC3B,uBAA+B,EAC/B,YAAsB;QAEtB,oCAAoC;QACpC,yBAAyB;QACzB,kBAAkB;QAClB,kBAAkB;QAClB,kBAAkB;QAClB,kBAAkB;QAClB,4BAA4B;QAC5B,uCAAuC;QACvC,aAAa;QACb,cAAc;QACd,IAAI,YAAY,EAAE;YAChB,IAAM,KAAK,GAAG,IAAI,CAAC,gCAAgC,CACjD,MAAM,EACN,MAAM,EACN,MAAM,EACN,MAAM,GAAG,CAAC,EACV,MAAM,GAAG,CAAC,EACV,MAAM,EACN,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACtD,mBAAmB,EACnB,uBAAuB,CACxB,CAAC;YACF,IAAI,KAAK,EAAE;gBACT,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACxC;YACD,IAAM,KAAK,GAAG,IAAI,CAAC,gCAAgC,CACjD,MAAM,EACN,MAAM,GAAG,CAAC,EACV,MAAM,GAAG,CAAC,EACV,MAAM,GAAG,CAAC,EACV,MAAM,GAAG,CAAC,EACV,MAAM,EACN,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACtD,mBAAmB,EACnB,uBAAuB,CACxB,CAAC;YACF,IAAI,KAAK,EAAE;gBACT,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACxC;SACF;aAAM;YACL,IAAM,IAAI,GAAG,IAAI,CAAC,+BAA+B,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,uBAAuB,CAAC,CAAC;YAC5H,IAAI,IAAI,EAAE;gBACR,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACvC;SACF;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACK,+DAAgC,GAAxC,UACE,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,UAAiC,EACjC,WAAmB,EACnB,uBAA+B;QAE/B,IAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB;QACrD,IAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACnC,IAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAEnC,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,IAAI,EAAE;YAC3E,MAAM,oEAAkE,OAAO,SAAI,OAAO,6BAA0B,CAAC;SACtH;QAED,IAAI,MAAM,GAAkB,EAAE,CAAC;QAE/B,6BAA6B;QAC7B,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAC3D,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,IAAI,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;SACzH;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAC3D,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACrF,yFAAyF;YACzF,MAAM,CAAC,IAAI,CAAC,IAAI,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;SACzH;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAC3D,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACrF,yFAAyF;YACzF,MAAM,CAAC,IAAI,CAAC,IAAI,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;SACzH;QAED,0EAA0E;QAC1E,yEAAyE;QACzE,2EAA2E;QAC3E,iBAAiB;QACjB,MAAM,GAAG,+CAAsB,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,CAAC,cAAc;QAEhF,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;YACtB,IAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7B,IAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;gBACvC,OAAO,CAAC,IAAI,CACV,+GAA+G,EAC/G,OAAO,EACP,OAAO,EACP,MAAM,CACP,CAAC;aACH;YACD,OAAO,IAAI,WAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;SACvC;aAAM;YACL,IAAI,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;gBACzC,OAAO,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;aACtG;YACD,OAAO,IAAI,CAAC;SACb;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,0DAA2B,GAA3B,UACE,CAAS,EACT,CAAS,EACT,KAAa,EACb,KAAa,EACb,mBAA2B,EAC3B,YAAoB;QAEpB,IAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxD,IAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAChE,sFAAsF;QACtF,IAAI,IAAI,CAAC,gCAAgC,CAAC,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,YAAY,CAAC,EAAE;YACxG,cAAc;YACd,IAAM,IAAI,GAAG,IAAI,WAAI,CAAC,IAAI,eAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,eAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YAClE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACvC;aAAM,IACL,CAAC,YAAY,IAAI,oBAAoB,CAAC,oBAAoB;YACxD,YAAY,IAAI,mBAAmB;YACnC,YAAY,IAAI,mBAAmB,CAAC;YACtC,CAAC,YAAY,IAAI,oBAAoB,CAAC,oBAAoB;gBACxD,YAAY,IAAI,mBAAmB;gBACnC,YAAY,IAAI,mBAAmB,CAAC,EACtC;YACA,oFAAoF;YACpF,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC;YAC7F,IAAM,UAAU,GAAG,IAAI,WAAI,CACzB,IAAI,eAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAChB,IAAI,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAC3F,CAAC;YACF,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SAC7C;aAAM,IACL,CAAC,YAAY,IAAI,oBAAoB,CAAC,oBAAoB;YACxD,YAAY,IAAI,mBAAmB;YACnC,YAAY,IAAI,mBAAmB,CAAC;YACtC,CAAC,YAAY,IAAI,oBAAoB,CAAC,oBAAoB;gBACxD,YAAY,IAAI,mBAAmB;gBACnC,YAAY,IAAI,mBAAmB,CAAC,EACtC;YACA,qFAAqF;YACrF,IAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC;YAC7F,IAAM,UAAU,GAAG,IAAI,WAAI,CACzB,IAAI,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,EAC1F,IAAI,eAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CACzB,CAAC;YACF,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SAC7C;IACH,CAAC;IAED;;;;;;;;;OASG;IACK,+DAAgC,GAAxC,UAAyC,MAAc,EAAE,MAAc,EAAE,aAAqB,EAAE,YAAoB;QAClH,OAAO,CACL,CAAC,YAAY,IAAI,oBAAoB,CAAC,oBAAoB,IAAI,MAAM,IAAI,aAAa,IAAI,MAAM,IAAI,aAAa,CAAC;YACjH,CAAC,YAAY,IAAI,oBAAoB,CAAC,oBAAoB,IAAI,MAAM,IAAI,aAAa,IAAI,MAAM,IAAI,aAAa,CAAC,CAClH,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACK,wCAAS,GAAjB,UAAkB,IAAY,EAAE,IAAY,EAAE,QAAgB;QAC5D,OAAO,CAAC,IAAI,IAAI,QAAQ,IAAI,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,QAAQ,IAAI,QAAQ,IAAI,IAAI,CAAC,CAAC;IAC1F,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACK,2CAAY,GAApB,UAAqB,IAAY,EAAE,IAAY,EAAE,QAAgB;QAC/D,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;OAOG;IACK,mCAAI,GAAZ,UAAa,GAAW,EAAE,GAAW,EAAE,KAAa;QAClD,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;IACnC,CAAC;IArcM,wCAAmB,GAAG,CAAC,CAAC;IACxB,yCAAoB,GAAG,CAAC,CAAC;IACzB,yCAAoB,GAAG,CAAC,CAAC;IAoclC,2BAAC;CAAA,AA3cD,IA2cC;AA3cY,oDAAoB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Remove duplicate vertices (2d) from an array.
3
+ *
4
+ * This method war taken and refactored from an older demo.
5
+ *
6
+ * @author Ikaros Kappler
7
+ * @date 2021-07-13
8
+ * @modified 2023-10-28 Refactored and ported to Typescript.
9
+ * @version 1.0.0
10
+ */
11
+ import { Vertex } from "../../Vertex";
12
+ /**
13
+ * Filter the array and clear all duplicates.
14
+ *
15
+ * The original array is left unchanged. The vertices in the array are not cloned.
16
+ *
17
+ * @param {Vertex[]} vertices
18
+ * @param {number=EPS} epsilon
19
+ * @return {Vertex[]}
20
+ */
21
+ export declare const clearDuplicateVertices: (vertices: Vertex[], epsilon?: number) => Vertex[];
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * Remove duplicate vertices (2d) from an array.
4
+ *
5
+ * This method war taken and refactored from an older demo.
6
+ *
7
+ * @author Ikaros Kappler
8
+ * @date 2021-07-13
9
+ * @modified 2023-10-28 Refactored and ported to Typescript.
10
+ * @version 1.0.0
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.clearDuplicateVertices = void 0;
14
+ var EPS = 0.000001;
15
+ /**
16
+ * Filter the array and clear all duplicates.
17
+ *
18
+ * The original array is left unchanged. The vertices in the array are not cloned.
19
+ *
20
+ * @param {Vertex[]} vertices
21
+ * @param {number=EPS} epsilon
22
+ * @return {Vertex[]}
23
+ */
24
+ var clearDuplicateVertices = function (vertices, epsilon) {
25
+ if (typeof epsilon === "undefined") {
26
+ epsilon = EPS;
27
+ }
28
+ var result = [];
29
+ for (var i = 0; i < vertices.length; i++) {
30
+ if (!containsElementFrom(vertices, vertices[i], i + 1, epsilon)) {
31
+ result.push(vertices[i]);
32
+ }
33
+ }
34
+ return result;
35
+ };
36
+ exports.clearDuplicateVertices = clearDuplicateVertices;
37
+ var isCloseTo = function (vertA, vertB, eps) {
38
+ return vertA.distance(vertB) < eps;
39
+ };
40
+ var containsElementFrom = function (vertices, vertex, fromIndex, epsilon) {
41
+ for (var i = fromIndex; i < vertices.length; i++) {
42
+ if (isCloseTo(vertices[i], vertex, epsilon)) {
43
+ return true;
44
+ }
45
+ }
46
+ return false;
47
+ };
48
+ //# sourceMappingURL=clearDuplicateVertices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clearDuplicateVertices.js","sourceRoot":"","sources":["../../../ts/utils/algorithms/clearDuplicateVertices.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAIH,IAAM,GAAG,GAAW,QAAQ,CAAC;AAE7B;;;;;;;;GAQG;AACI,IAAM,sBAAsB,GAAG,UAAC,QAAkB,EAAE,OAAgB;IACzE,IAAI,OAAO,OAAO,KAAK,WAAW,EAAE;QAClC,OAAO,GAAG,GAAG,CAAC;KACf;IACD,IAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACxC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE;YAC/D,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;SAC1B;KACF;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAXW,QAAA,sBAAsB,0BAWjC;AAEF,IAAM,SAAS,GAAG,UAAC,KAAa,EAAE,KAAa,EAAE,GAAW;IAC1D,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;AACrC,CAAC,CAAC;AAEF,IAAM,mBAAmB,GAAG,UAAC,QAAuB,EAAE,MAAc,EAAE,SAAiB,EAAE,OAAe;IACtG,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QAChD,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;YAC3C,OAAO,IAAI,CAAC;SACb;KACF;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
@@ -7,7 +7,8 @@
7
7
  * @author Ikaros Kappler
8
8
  * @date 2020-03-30
9
9
  * @modified 2020-04-03 Added empty default global object 'utils'. Added createGUI as an optional child.
10
- * @version 1.0.1
10
+ * @modified 2023-09-29 Added try-catch for color attributes; invalid values might break construction of whole gui.
11
+ * @version 1.0.2
11
12
  **/
12
13
  var utils = (globalThis.utils = globalThis.utils || {});
13
14
 
@@ -168,15 +169,20 @@ globalThis.utils.createGUI = function (pb, props) {
168
169
  const _addDrawConfigElement = function (fold, basePath, conf) {
169
170
  for (var i in conf) {
170
171
  if (typeof conf[i] == "object") {
171
- if (conf[i].hasOwnProperty("color"))
172
- fold
173
- .addColor(conf[i], "color")
174
- .onChange(function () {
175
- _self.redraw();
176
- })
177
- .name(basePath + i + ".color")
178
- .title(basePath + i + ".color")
179
- .listen();
172
+ if (conf[i].hasOwnProperty("color")) {
173
+ try {
174
+ fold
175
+ .addColor(conf[i], "color")
176
+ .onChange(function () {
177
+ _self.redraw();
178
+ })
179
+ .name(basePath + i + ".color")
180
+ .title(basePath + i + ".color")
181
+ .listen();
182
+ } catch (e) {
183
+ console.error("[createGUI] Invalid color value, gui library cannot recognize.", conf[i]["color"]);
184
+ }
185
+ }
180
186
  if (conf[i].hasOwnProperty("lineWidth"))
181
187
  fold
182
188
  .add(conf[i], "lineWidth")