Skip to content

Commit 71e51ec

Browse files
committed
Pixel-based threshold for line detection.
1 parent db3f33d commit 71e51ec

File tree

3 files changed

+45
-37
lines changed

3 files changed

+45
-37
lines changed

source/engine/main.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ import { Unit } from './model/unit.js';
6666
import { ParameterListBuilder, ParameterListParser, CreateUrlBuilder, CreateUrlParser, CreateModelUrlParameters, ParameterConverter } from './parameters/parameterlist.js';
6767
import { ModelToThreeConversionParams, ModelToThreeConversionOutput, ThreeConversionStateHandler, ThreeNodeTree, ThreeMaterialHandler, ThreeMeshMaterialHandler, ConvertModelToThreeObject, MaterialGeometryType } from './threejs/threeconverter.js';
6868
import { ThreeModelLoader } from './threejs/threemodelloader.js';
69-
import { ThreeColorConverter, ThreeLinearToSRGBColorConverter, ThreeSRGBToLinearColorConverter, HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, CreateHighlightMaterial, CreateHighlightMaterials, DisposeThreeObjects, ShadingType } from './threejs/threeutils.js';
69+
import { ThreeColorConverter, ThreeLinearToSRGBColorConverter, ThreeSRGBToLinearColorConverter, HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, CreateHighlightMaterial, CreateHighlightMaterials, DisposeThreeObjects, GetLineSegmentsProjectedDistance, ShadingType } from './threejs/threeutils.js';
7070
import { Camera, CameraIsEqual3D, NavigationMode, ProjectionMode } from './viewer/camera.js';
7171
import { GetIntegerFromStyle, GetDomElementExternalWidth, GetDomElementExternalHeight, GetDomElementInnerDimensions, GetDomElementClientCoordinates, CreateDomElement, AddDomElement, AddDiv, ClearDomElement, InsertDomElementBefore, InsertDomElementAfter, ShowDomElement, IsDomElementVisible, SetDomElementWidth, SetDomElementHeight, GetDomElementOuterWidth, GetDomElementOuterHeight, SetDomElementOuterWidth, SetDomElementOuterHeight, CreateDiv } from './viewer/domutils.js';
7272
import { EmbeddedViewer, Init3DViewerFromUrlList, Init3DViewerFromFileList, Init3DViewerElements } from './viewer/embeddedviewer.js';
@@ -305,6 +305,7 @@ export {
305305
CreateHighlightMaterial,
306306
CreateHighlightMaterials,
307307
DisposeThreeObjects,
308+
GetLineSegmentsProjectedDistance,
308309
ShadingType,
309310
Camera,
310311
CameraIsEqual3D,

source/engine/threejs/threeutils.js

+31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Coord2D } from '../geometry/coord2d.js';
22
import { Coord3D } from '../geometry/coord3d.js';
3+
import { Segment2D, SegmentPointDistance2D } from '../geometry/line2d.js';
34
import { RGBColorFromFloatComponents } from '../model/color.js';
45
import { MaterialType } from '../model/material.js';
56
import { Mesh } from '../model/mesh.js';
@@ -272,3 +273,33 @@ export function DisposeThreeObjects (mainObject)
272273
}
273274
});
274275
}
276+
277+
export function GetLineSegmentsProjectedDistance (camera, canvasWidth, canvasHeight, lineSegments, screenPoint)
278+
{
279+
function GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, index)
280+
{
281+
let vertex = new THREE.Vector3 (
282+
vertices[3 * index],
283+
vertices[3 * index + 1],
284+
vertices[3 * index + 2]
285+
);
286+
vertex.applyMatrix4 (lineSegments.matrixWorld);
287+
let projected = vertex.project (camera);
288+
return new Coord2D (
289+
(projected.x + 1.0) * canvasWidth / 2.0,
290+
-(projected.y - 1.0) * canvasHeight / 2.0
291+
);
292+
}
293+
294+
let vertices = lineSegments.geometry.attributes.position.array;
295+
let segmentCount = vertices.length / 6;
296+
let distance = Infinity;
297+
for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) {
298+
let segment = new Segment2D (
299+
GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, 2 * segmentIndex),
300+
GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, 2 * segmentIndex + 1)
301+
);
302+
distance = Math.min (distance, SegmentPointDistance2D (segment, screenPoint));
303+
}
304+
return distance;
305+
}

source/engine/viewer/viewermodel.js

+12-36
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { RGBColor } from '../model/color.js';
2-
import { ConvertColorToThreeColor, DisposeThreeObjects } from '../threejs/threeutils.js';
2+
import { ConvertColorToThreeColor, DisposeThreeObjects, GetLineSegmentsProjectedDistance } from '../threejs/threeutils.js';
33

44
import * as THREE from 'three';
55

6+
const LineThresholdInPixels = 10.0;
7+
68
export const IntersectionMode =
79
{
810
MeshOnly : 1,
@@ -127,15 +129,13 @@ export class ViewerMainModel
127129
this.edgeSettings = new EdgeSettings (false, new RGBColor (0, 0, 0), 1);
128130
this.hasLines = false;
129131
this.hasPolygonOffset = false;
130-
this.fullBoundingBox = null;
131132
}
132133

133134
SetMainObject (mainObject)
134135
{
135136
this.mainModel.SetRootObject (mainObject);
136137
this.hasLines = false;
137138
this.hasPolygonOffset = false;
138-
this.fullBoundingBox = null;
139139

140140
this.EnumerateLines ((line) => {
141141
this.hasLines = true;
@@ -200,17 +200,6 @@ export class ViewerMainModel
200200
this.UpdatePolygonOffset ();
201201
}
202202

203-
GetFullBoundingBox ()
204-
{
205-
if (this.fullBoundingBox !== null) {
206-
return this.fullBoundingBox;
207-
}
208-
this.fullBoundingBox = this.GetBoundingBox (() => {
209-
return true;
210-
});
211-
return this.fullBoundingBox;
212-
}
213-
214203
GetBoundingBox (needToProcess)
215204
{
216205
let hasMesh = false;
@@ -311,18 +300,6 @@ export class ViewerMainModel
311300

312301
GetMeshIntersectionUnderMouse (intersectionMode, mouseCoords, camera, width, height)
313302
{
314-
function CalculateLineThreshold (mousePos, camera, boundingBoxCenter)
315-
{
316-
let thresholdInScreenCoordinates = 15.0;
317-
let frustumRange = camera.far - camera.near;
318-
let cameraDistanceFromCenter = boundingBoxCenter.distanceTo (camera.position);
319-
let distanceInFrustumRatio = cameraDistanceFromCenter / frustumRange;
320-
let zValue = -1.0 + 2.0 * distanceInFrustumRatio;
321-
let referencePoint1 = new THREE.Vector3 (mousePos.x, mousePos.y, zValue).unproject (camera);
322-
let referencePoint2 = new THREE.Vector3 (mousePos.x + thresholdInScreenCoordinates, mousePos.y, zValue).unproject (camera);
323-
return referencePoint1.distanceTo (referencePoint2);
324-
}
325-
326303
if (this.mainModel.IsEmpty ()) {
327304
return null;
328305
}
@@ -336,16 +313,9 @@ export class ViewerMainModel
336313
mousePos.y = -(mouseCoords.y / height) * 2 + 1;
337314

338315
let raycaster = new THREE.Raycaster ();
339-
if (this.hasLines) {
340-
let boundingBox = this.GetFullBoundingBox ();
341-
if (boundingBox !== null) {
342-
let boundingBoxCenter = new THREE.Vector3 (0.0, 0.0, 0.0);
343-
boundingBox.getCenter (boundingBoxCenter);
344-
raycaster.params.Line.threshold = CalculateLineThreshold (mousePos, camera, boundingBoxCenter);
345-
}
346-
}
347-
348316
raycaster.setFromCamera (mousePos, camera);
317+
raycaster.params.Line.threshold = 10.0;
318+
349319
let iSectObjects = raycaster.intersectObject (this.mainModel.GetRootObject (), true);
350320
for (let i = 0; i < iSectObjects.length; i++) {
351321
let iSectObject = iSectObjects[i];
@@ -355,7 +325,13 @@ export class ViewerMainModel
355325
if (intersectionMode === IntersectionMode.MeshOnly && iSectObject.object.isLineSegments) {
356326
continue;
357327
}
358-
if (iSectObject.object.isMesh || iSectObject.object.isLineSegments) {
328+
if (iSectObject.object.isMesh) {
329+
return iSectObject;
330+
} else if (iSectObject.object.isLineSegments) {
331+
let distance = GetLineSegmentsProjectedDistance (camera, width, height, iSectObject.object, mouseCoords);
332+
if (distance > LineThresholdInPixels) {
333+
continue;
334+
}
359335
return iSectObject;
360336
}
361337
}

0 commit comments

Comments
 (0)