@2112-lab/central-plant 0.1.39 → 0.1.41
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/dist/bundle/index.js +7991 -7054
- package/dist/cjs/src/core/centralPlant.js +48 -3
- package/dist/cjs/src/core/centralPlantInternals.js +75 -566
- package/dist/cjs/src/core/sceneViewer.js +38 -13
- package/dist/cjs/src/index.js +6 -4
- package/dist/cjs/src/managers/components/pathfindingManager.js +75 -60
- package/dist/cjs/src/managers/components/transformOperationsManager.js +929 -0
- package/dist/cjs/src/managers/controls/keyboardControlsManager.js +57 -1
- package/dist/cjs/src/managers/controls/transformControls.js +11 -3
- package/dist/cjs/src/managers/controls/transformControlsManager.js +563 -263
- package/dist/cjs/src/managers/pathfinding/ConnectorManager.js +385 -0
- package/dist/cjs/src/managers/pathfinding/PathIntersectionDetector.js +387 -0
- package/dist/cjs/src/managers/pathfinding/PathRenderingManager.js +401 -0
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +378 -0
- package/dist/cjs/src/managers/pathfinding/sceneDataManager.js +256 -0
- package/dist/cjs/src/managers/scene/animationManager.js +145 -0
- package/dist/cjs/src/managers/scene/sceneExportManager.js +14 -13
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +516 -21
- package/dist/cjs/src/managers/scene/sceneTooltipsManager.js +1 -8
- package/dist/cjs/src/managers/system/operationHistoryManager.js +414 -0
- package/dist/cjs/src/managers/system/settingsManager.js +2 -1
- package/dist/cjs/src/utils/objectTypes.js +5 -7
- package/dist/esm/src/core/centralPlant.js +48 -3
- package/dist/esm/src/core/centralPlantInternals.js +76 -567
- package/dist/esm/src/core/sceneViewer.js +38 -13
- package/dist/esm/src/index.js +4 -3
- package/dist/esm/src/managers/components/pathfindingManager.js +75 -60
- package/dist/esm/src/managers/components/transformOperationsManager.js +904 -0
- package/dist/esm/src/managers/controls/keyboardControlsManager.js +57 -1
- package/dist/esm/src/managers/controls/transformControls.js +11 -3
- package/dist/esm/src/managers/controls/transformControlsManager.js +564 -264
- package/dist/esm/src/managers/pathfinding/ConnectorManager.js +361 -0
- package/dist/esm/src/managers/pathfinding/PathIntersectionDetector.js +363 -0
- package/dist/esm/src/managers/pathfinding/PathRenderingManager.js +377 -0
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +374 -0
- package/dist/esm/src/managers/pathfinding/sceneDataManager.js +232 -0
- package/dist/esm/src/managers/scene/animationManager.js +141 -0
- package/dist/esm/src/managers/scene/sceneExportManager.js +14 -13
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +516 -21
- package/dist/esm/src/managers/scene/sceneTooltipsManager.js +1 -8
- package/dist/esm/src/managers/system/operationHistoryManager.js +409 -0
- package/dist/esm/src/managers/system/settingsManager.js +2 -1
- package/dist/esm/src/utils/objectTypes.js +5 -7
- package/dist/index.d.ts +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
|
|
6
|
+
var THREE = require('three');
|
|
7
|
+
|
|
8
|
+
function _interopNamespace(e) {
|
|
9
|
+
if (e && e.__esModule) return e;
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n["default"] = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* PathIntersectionDetector - Detects intersections between pipe paths
|
|
30
|
+
*
|
|
31
|
+
* This class handles all intersection detection logic for both computed paths
|
|
32
|
+
* (from pathfinding) and manual segments (user-positioned pipes).
|
|
33
|
+
*
|
|
34
|
+
* @class PathIntersectionDetector
|
|
35
|
+
*/
|
|
36
|
+
var PathIntersectionDetector = /*#__PURE__*/function () {
|
|
37
|
+
/**
|
|
38
|
+
* Create a new PathIntersectionDetector
|
|
39
|
+
* @param {Object} sceneViewer - Reference to the scene viewer
|
|
40
|
+
*/
|
|
41
|
+
function PathIntersectionDetector(sceneViewer) {
|
|
42
|
+
_rollupPluginBabelHelpers.classCallCheck(this, PathIntersectionDetector);
|
|
43
|
+
this.sceneViewer = sceneViewer;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check for intersections between paths
|
|
48
|
+
* @param {Array} paths - Array of path objects from pathfinder
|
|
49
|
+
* @param {number} tolerance - Distance tolerance for considering pipes as intersecting (default: 0.2)
|
|
50
|
+
* @param {boolean} includeManualSegments - Whether to include manual segments in the check (default: true)
|
|
51
|
+
* @returns {Object} Intersection results
|
|
52
|
+
* @property {boolean} hasIntersections - Whether any intersections were found
|
|
53
|
+
* @property {Array<Object>} intersections - Array of intersection details
|
|
54
|
+
* @property {number} count - Total number of intersections found
|
|
55
|
+
*/
|
|
56
|
+
return _rollupPluginBabelHelpers.createClass(PathIntersectionDetector, [{
|
|
57
|
+
key: "checkPathIntersections",
|
|
58
|
+
value: function checkPathIntersections(paths) {
|
|
59
|
+
var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.2;
|
|
60
|
+
var includeManualSegments = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
61
|
+
var intersections = [];
|
|
62
|
+
|
|
63
|
+
// Convert all paths to line segments for comparison
|
|
64
|
+
var pathSegments = paths.map(function (pathData, pathIndex) {
|
|
65
|
+
if (!pathData.path || pathData.path.length < 2) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
var segments = [];
|
|
69
|
+
var pathPoints = pathData.path.map(function (point) {
|
|
70
|
+
if (point instanceof THREE__namespace.Vector3) {
|
|
71
|
+
return point.clone();
|
|
72
|
+
} else if (Array.isArray(point)) {
|
|
73
|
+
return new THREE__namespace.Vector3().fromArray(point);
|
|
74
|
+
} else if (point.x !== undefined && point.y !== undefined && point.z !== undefined) {
|
|
75
|
+
return new THREE__namespace.Vector3(point.x, point.y, point.z);
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}).filter(function (p) {
|
|
79
|
+
return p !== null;
|
|
80
|
+
});
|
|
81
|
+
for (var i = 0; i < pathPoints.length - 1; i++) {
|
|
82
|
+
segments.push({
|
|
83
|
+
start: pathPoints[i],
|
|
84
|
+
end: pathPoints[i + 1],
|
|
85
|
+
pathIndex: pathIndex,
|
|
86
|
+
segmentIndex: i,
|
|
87
|
+
pathFrom: pathData.from,
|
|
88
|
+
pathTo: pathData.to,
|
|
89
|
+
isFirstSegment: i === 0,
|
|
90
|
+
isLastSegment: i === pathPoints.length - 2,
|
|
91
|
+
isManual: false // Computed path segment
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return segments;
|
|
95
|
+
}).filter(function (s) {
|
|
96
|
+
return s !== null;
|
|
97
|
+
}).flat();
|
|
98
|
+
|
|
99
|
+
// Add manual segments if requested
|
|
100
|
+
if (includeManualSegments) {
|
|
101
|
+
var manualSegments = this._collectManualSegments(pathSegments.length);
|
|
102
|
+
pathSegments.push.apply(pathSegments, _rollupPluginBabelHelpers.toConsumableArray(manualSegments));
|
|
103
|
+
console.log("\uD83D\uDCE6 Added ".concat(manualSegments.length, " manual segment(s) to intersection check"));
|
|
104
|
+
}
|
|
105
|
+
console.log("\uD83D\uDD0D Checking ".concat(pathSegments.length, " segments for intersections..."));
|
|
106
|
+
|
|
107
|
+
// Check each pair of segments
|
|
108
|
+
for (var i = 0; i < pathSegments.length; i++) {
|
|
109
|
+
for (var j = i + 1; j < pathSegments.length; j++) {
|
|
110
|
+
var seg1 = pathSegments[i];
|
|
111
|
+
var seg2 = pathSegments[j];
|
|
112
|
+
|
|
113
|
+
// Skip if segments are from the same path
|
|
114
|
+
if (seg1.pathIndex === seg2.pathIndex) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Check if segments intersect
|
|
119
|
+
var intersection = this._checkLineSegmentIntersection(seg1.start, seg1.end, seg2.start, seg2.end, tolerance);
|
|
120
|
+
if (intersection) {
|
|
121
|
+
// Check if this is a shared endpoint (connector/gateway)
|
|
122
|
+
// Paths naturally touch at shared connectors - this is not an intersection
|
|
123
|
+
var endpointTolerance = 0.01; // Very small tolerance for endpoint matching
|
|
124
|
+
var touchingAtEndpoint = this._areSegmentsTouchingAtSharedEndpoint(seg1, seg2, endpointTolerance);
|
|
125
|
+
if (touchingAtEndpoint) {
|
|
126
|
+
console.log("\u2139\uFE0F Segments share endpoint (not an intersection): ".concat(seg1.pathFrom, " \u2194 ").concat(seg2.pathFrom));
|
|
127
|
+
continue; // Skip this - it's a valid shared connection point
|
|
128
|
+
}
|
|
129
|
+
intersections.push({
|
|
130
|
+
path1: {
|
|
131
|
+
from: seg1.pathFrom,
|
|
132
|
+
to: seg1.pathTo,
|
|
133
|
+
segmentIndex: seg1.segmentIndex,
|
|
134
|
+
isManual: seg1.isManual
|
|
135
|
+
},
|
|
136
|
+
path2: {
|
|
137
|
+
from: seg2.pathFrom,
|
|
138
|
+
to: seg2.pathTo,
|
|
139
|
+
segmentIndex: seg2.segmentIndex,
|
|
140
|
+
isManual: seg2.isManual
|
|
141
|
+
},
|
|
142
|
+
point: intersection.point,
|
|
143
|
+
distance: intersection.distance,
|
|
144
|
+
type: intersection.type
|
|
145
|
+
});
|
|
146
|
+
var seg1Type = seg1.isManual ? 'manual' : 'computed';
|
|
147
|
+
var seg2Type = seg2.isManual ? 'manual' : 'computed';
|
|
148
|
+
console.log("\u26A0\uFE0F Intersection found between paths:\n Path 1 (".concat(seg1Type, "): ").concat(seg1.pathFrom, " \u2192 ").concat(seg1.pathTo, " (segment ").concat(seg1.segmentIndex, ")\n Path 2 (").concat(seg2Type, "): ").concat(seg2.pathFrom, " \u2192 ").concat(seg2.pathTo, " (segment ").concat(seg2.segmentIndex, ")\n Distance: ").concat(intersection.distance.toFixed(4), "\n Type: ").concat(intersection.type));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
var result = {
|
|
153
|
+
hasIntersections: intersections.length > 0,
|
|
154
|
+
intersections: intersections,
|
|
155
|
+
count: intersections.length
|
|
156
|
+
};
|
|
157
|
+
if (result.hasIntersections) {
|
|
158
|
+
console.log("\uD83D\uDEA8 Found ".concat(result.count, " intersection(s) between paths"));
|
|
159
|
+
} else {
|
|
160
|
+
console.log("\u2705 No path intersections detected");
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Collect manual segments from the scene and convert them to path segments format
|
|
167
|
+
* @private
|
|
168
|
+
* @param {number} startingPathIndex - The starting index for manual segment paths
|
|
169
|
+
* @returns {Array} Array of segment objects in the same format as computed paths
|
|
170
|
+
*/
|
|
171
|
+
}, {
|
|
172
|
+
key: "_collectManualSegments",
|
|
173
|
+
value: function _collectManualSegments(startingPathIndex) {
|
|
174
|
+
var _this = this;
|
|
175
|
+
var manualSegments = [];
|
|
176
|
+
var sceneViewer = this.sceneViewer;
|
|
177
|
+
var pathIndex = startingPathIndex;
|
|
178
|
+
|
|
179
|
+
// Traverse the scene to find manual segments (lowercase "Segment-")
|
|
180
|
+
sceneViewer.scene.traverse(function (obj) {
|
|
181
|
+
var _obj$userData, _obj$userData2;
|
|
182
|
+
if (obj.uuid && obj.uuid.startsWith('Segment-') && ((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType) === 'segment' && ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.isDeclared) === true) {
|
|
183
|
+
// Calculate segment endpoints from the cylinder geometry
|
|
184
|
+
var endpoints = _this._calculateSegmentEndpoints(obj);
|
|
185
|
+
|
|
186
|
+
// Create segment object in the same format as computed paths
|
|
187
|
+
manualSegments.push({
|
|
188
|
+
start: endpoints.start,
|
|
189
|
+
end: endpoints.end,
|
|
190
|
+
pathIndex: pathIndex,
|
|
191
|
+
segmentIndex: 0,
|
|
192
|
+
// Manual segments are single-segment paths
|
|
193
|
+
pathFrom: obj.userData.pathFrom || obj.uuid,
|
|
194
|
+
pathTo: obj.userData.pathTo || obj.uuid,
|
|
195
|
+
isFirstSegment: true,
|
|
196
|
+
isLastSegment: true,
|
|
197
|
+
isManual: true,
|
|
198
|
+
// Flag to identify manual segments
|
|
199
|
+
segmentUuid: obj.uuid
|
|
200
|
+
});
|
|
201
|
+
pathIndex++;
|
|
202
|
+
console.log("\uD83D\uDCE6 Collected manual segment: ".concat(obj.uuid));
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
return manualSegments;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Calculate the start and end points of a pipe segment in world coordinates
|
|
210
|
+
* @private
|
|
211
|
+
* @param {THREE.Object3D} segment - The pipe segment
|
|
212
|
+
* @returns {Object} Object with start and end points
|
|
213
|
+
*/
|
|
214
|
+
}, {
|
|
215
|
+
key: "_calculateSegmentEndpoints",
|
|
216
|
+
value: function _calculateSegmentEndpoints(segment) {
|
|
217
|
+
// Get the segment's geometry to determine its length and orientation
|
|
218
|
+
var geometry = segment.geometry;
|
|
219
|
+
var length = geometry.parameters.height || 1;
|
|
220
|
+
|
|
221
|
+
// Calculate start and end points based on segment position and orientation
|
|
222
|
+
var startPoint = new THREE__namespace.Vector3();
|
|
223
|
+
var endPoint = new THREE__namespace.Vector3();
|
|
224
|
+
|
|
225
|
+
// Get the segment's direction vector
|
|
226
|
+
var direction = new THREE__namespace.Vector3(0, 1, 0);
|
|
227
|
+
direction.applyQuaternion(segment.quaternion);
|
|
228
|
+
|
|
229
|
+
// Calculate start point (half length back from center)
|
|
230
|
+
startPoint.copy(segment.position).sub(direction.clone().multiplyScalar(length / 2));
|
|
231
|
+
|
|
232
|
+
// Calculate end point (half length forward from center)
|
|
233
|
+
endPoint.copy(segment.position).add(direction.clone().multiplyScalar(length / 2));
|
|
234
|
+
return {
|
|
235
|
+
start: startPoint,
|
|
236
|
+
end: endPoint
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Check if two segments are touching at a shared endpoint (connector/gateway)
|
|
242
|
+
* @private
|
|
243
|
+
* @param {Object} seg1 - First segment
|
|
244
|
+
* @param {Object} seg2 - Second segment
|
|
245
|
+
* @param {number} tolerance - Distance tolerance for considering points as the same
|
|
246
|
+
* @returns {boolean} True if segments share an endpoint
|
|
247
|
+
*/
|
|
248
|
+
}, {
|
|
249
|
+
key: "_areSegmentsTouchingAtSharedEndpoint",
|
|
250
|
+
value: function _areSegmentsTouchingAtSharedEndpoint(seg1, seg2, tolerance) {
|
|
251
|
+
// Check all possible endpoint combinations
|
|
252
|
+
var endpoints = [
|
|
253
|
+
// seg1.start with seg2 endpoints
|
|
254
|
+
{
|
|
255
|
+
p1: seg1.start,
|
|
256
|
+
p2: seg2.start,
|
|
257
|
+
isSeg1Start: true,
|
|
258
|
+
isSeg2Start: true
|
|
259
|
+
}, {
|
|
260
|
+
p1: seg1.start,
|
|
261
|
+
p2: seg2.end,
|
|
262
|
+
isSeg1Start: true,
|
|
263
|
+
isSeg2Start: false
|
|
264
|
+
},
|
|
265
|
+
// seg1.end with seg2 endpoints
|
|
266
|
+
{
|
|
267
|
+
p1: seg1.end,
|
|
268
|
+
p2: seg2.start,
|
|
269
|
+
isSeg1Start: false,
|
|
270
|
+
isSeg2Start: true
|
|
271
|
+
}, {
|
|
272
|
+
p1: seg1.end,
|
|
273
|
+
p2: seg2.end,
|
|
274
|
+
isSeg1Start: false,
|
|
275
|
+
isSeg2Start: false
|
|
276
|
+
}];
|
|
277
|
+
for (var _i = 0, _endpoints = endpoints; _i < _endpoints.length; _i++) {
|
|
278
|
+
var _endpoints$_i = _endpoints[_i],
|
|
279
|
+
p1 = _endpoints$_i.p1,
|
|
280
|
+
p2 = _endpoints$_i.p2,
|
|
281
|
+
isSeg1Start = _endpoints$_i.isSeg1Start,
|
|
282
|
+
isSeg2Start = _endpoints$_i.isSeg2Start;
|
|
283
|
+
var distance = p1.distanceTo(p2);
|
|
284
|
+
if (distance <= tolerance) {
|
|
285
|
+
// Verify this is actually an endpoint of the path (not just any segment point)
|
|
286
|
+
var isSeg1Endpoint = isSeg1Start && seg1.isFirstSegment || !isSeg1Start && seg1.isLastSegment;
|
|
287
|
+
var isSeg2Endpoint = isSeg2Start && seg2.isFirstSegment || !isSeg2Start && seg2.isLastSegment;
|
|
288
|
+
|
|
289
|
+
// Only count as shared endpoint if at least one is a path endpoint
|
|
290
|
+
// (This handles both connector-to-connector and connector-to-gateway cases)
|
|
291
|
+
if (isSeg1Endpoint || isSeg2Endpoint) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Check if two line segments intersect or come within tolerance distance
|
|
301
|
+
* @private
|
|
302
|
+
* @param {THREE.Vector3} p1 - Start of first segment
|
|
303
|
+
* @param {THREE.Vector3} p2 - End of first segment
|
|
304
|
+
* @param {THREE.Vector3} p3 - Start of second segment
|
|
305
|
+
* @param {THREE.Vector3} p4 - End of second segment
|
|
306
|
+
* @param {number} tolerance - Distance tolerance
|
|
307
|
+
* @returns {Object|null} Intersection details or null
|
|
308
|
+
*/
|
|
309
|
+
}, {
|
|
310
|
+
key: "_checkLineSegmentIntersection",
|
|
311
|
+
value: function _checkLineSegmentIntersection(p1, p2, p3, p4, tolerance) {
|
|
312
|
+
// Calculate closest points on two line segments
|
|
313
|
+
var d1 = new THREE__namespace.Vector3().subVectors(p2, p1); // Direction of segment 1
|
|
314
|
+
var d2 = new THREE__namespace.Vector3().subVectors(p4, p3); // Direction of segment 2
|
|
315
|
+
var r = new THREE__namespace.Vector3().subVectors(p1, p3);
|
|
316
|
+
var a = d1.dot(d1);
|
|
317
|
+
var b = d1.dot(d2);
|
|
318
|
+
var c = d2.dot(d2);
|
|
319
|
+
var d = d1.dot(r);
|
|
320
|
+
var e = d2.dot(r);
|
|
321
|
+
var denom = a * c - b * b;
|
|
322
|
+
|
|
323
|
+
// Check if lines are parallel
|
|
324
|
+
if (Math.abs(denom) < 1e-10) {
|
|
325
|
+
// Lines are parallel, check if they're close enough
|
|
326
|
+
var distToLine = this._distancePointToLineSegment(p3, p1, p2);
|
|
327
|
+
if (distToLine <= tolerance) {
|
|
328
|
+
return {
|
|
329
|
+
point: p3.clone(),
|
|
330
|
+
distance: distToLine,
|
|
331
|
+
type: 'parallel'
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Calculate parameters for closest points
|
|
338
|
+
var s = (b * e - c * d) / denom;
|
|
339
|
+
var t = (a * e - b * d) / denom;
|
|
340
|
+
|
|
341
|
+
// Clamp to segment bounds
|
|
342
|
+
s = Math.max(0, Math.min(1, s));
|
|
343
|
+
t = Math.max(0, Math.min(1, t));
|
|
344
|
+
|
|
345
|
+
// Calculate closest points
|
|
346
|
+
var closestPoint1 = new THREE__namespace.Vector3().addVectors(p1, d1.clone().multiplyScalar(s));
|
|
347
|
+
var closestPoint2 = new THREE__namespace.Vector3().addVectors(p3, d2.clone().multiplyScalar(t));
|
|
348
|
+
|
|
349
|
+
// Calculate distance between closest points
|
|
350
|
+
var distance = closestPoint1.distanceTo(closestPoint2);
|
|
351
|
+
|
|
352
|
+
// Check if within tolerance
|
|
353
|
+
if (distance <= tolerance) {
|
|
354
|
+
var midPoint = new THREE__namespace.Vector3().addVectors(closestPoint1, closestPoint2).multiplyScalar(0.5);
|
|
355
|
+
return {
|
|
356
|
+
point: midPoint,
|
|
357
|
+
distance: distance,
|
|
358
|
+
type: distance < 0.01 ? 'crossing' : 'near'
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Calculate distance from a point to a line segment
|
|
366
|
+
* @private
|
|
367
|
+
* @param {THREE.Vector3} point - The point
|
|
368
|
+
* @param {THREE.Vector3} lineStart - Start of line segment
|
|
369
|
+
* @param {THREE.Vector3} lineEnd - End of line segment
|
|
370
|
+
* @returns {number} Distance to line segment
|
|
371
|
+
*/
|
|
372
|
+
}, {
|
|
373
|
+
key: "_distancePointToLineSegment",
|
|
374
|
+
value: function _distancePointToLineSegment(point, lineStart, lineEnd) {
|
|
375
|
+
var line = new THREE__namespace.Vector3().subVectors(lineEnd, lineStart);
|
|
376
|
+
var lineLength = line.length();
|
|
377
|
+
if (lineLength < 1e-10) {
|
|
378
|
+
return point.distanceTo(lineStart);
|
|
379
|
+
}
|
|
380
|
+
var t = Math.max(0, Math.min(1, new THREE__namespace.Vector3().subVectors(point, lineStart).dot(line) / (lineLength * lineLength)));
|
|
381
|
+
var projection = new THREE__namespace.Vector3().addVectors(lineStart, line.multiplyScalar(t));
|
|
382
|
+
return point.distanceTo(projection);
|
|
383
|
+
}
|
|
384
|
+
}]);
|
|
385
|
+
}();
|
|
386
|
+
|
|
387
|
+
exports.PathIntersectionDetector = PathIntersectionDetector;
|