Pixel-based threshold for line detection.

This commit is contained in:
kovacsv 2023-12-26 14:29:20 +01:00
parent db3f33d52f
commit 71e51ecf58
3 changed files with 45 additions and 37 deletions

View File

@ -66,7 +66,7 @@ import { Unit } from './model/unit.js';
import { ParameterListBuilder, ParameterListParser, CreateUrlBuilder, CreateUrlParser, CreateModelUrlParameters, ParameterConverter } from './parameters/parameterlist.js';
import { ModelToThreeConversionParams, ModelToThreeConversionOutput, ThreeConversionStateHandler, ThreeNodeTree, ThreeMaterialHandler, ThreeMeshMaterialHandler, ConvertModelToThreeObject, MaterialGeometryType } from './threejs/threeconverter.js';
import { ThreeModelLoader } from './threejs/threemodelloader.js';
import { ThreeColorConverter, ThreeLinearToSRGBColorConverter, ThreeSRGBToLinearColorConverter, HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, CreateHighlightMaterial, CreateHighlightMaterials, DisposeThreeObjects, ShadingType } from './threejs/threeutils.js';
import { ThreeColorConverter, ThreeLinearToSRGBColorConverter, ThreeSRGBToLinearColorConverter, HasHighpDriverIssue, GetShadingType, ConvertThreeColorToColor, ConvertColorToThreeColor, ConvertThreeGeometryToMesh, CreateHighlightMaterial, CreateHighlightMaterials, DisposeThreeObjects, GetLineSegmentsProjectedDistance, ShadingType } from './threejs/threeutils.js';
import { Camera, CameraIsEqual3D, NavigationMode, ProjectionMode } from './viewer/camera.js';
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';
import { EmbeddedViewer, Init3DViewerFromUrlList, Init3DViewerFromFileList, Init3DViewerElements } from './viewer/embeddedviewer.js';
@ -305,6 +305,7 @@ export {
CreateHighlightMaterial,
CreateHighlightMaterials,
DisposeThreeObjects,
GetLineSegmentsProjectedDistance,
ShadingType,
Camera,
CameraIsEqual3D,

View File

@ -1,5 +1,6 @@
import { Coord2D } from '../geometry/coord2d.js';
import { Coord3D } from '../geometry/coord3d.js';
import { Segment2D, SegmentPointDistance2D } from '../geometry/line2d.js';
import { RGBColorFromFloatComponents } from '../model/color.js';
import { MaterialType } from '../model/material.js';
import { Mesh } from '../model/mesh.js';
@ -272,3 +273,33 @@ export function DisposeThreeObjects (mainObject)
}
});
}
export function GetLineSegmentsProjectedDistance (camera, canvasWidth, canvasHeight, lineSegments, screenPoint)
{
function GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, index)
{
let vertex = new THREE.Vector3 (
vertices[3 * index],
vertices[3 * index + 1],
vertices[3 * index + 2]
);
vertex.applyMatrix4 (lineSegments.matrixWorld);
let projected = vertex.project (camera);
return new Coord2D (
(projected.x + 1.0) * canvasWidth / 2.0,
-(projected.y - 1.0) * canvasHeight / 2.0
);
}
let vertices = lineSegments.geometry.attributes.position.array;
let segmentCount = vertices.length / 6;
let distance = Infinity;
for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) {
let segment = new Segment2D (
GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, 2 * segmentIndex),
GetProjectedVertex (camera, canvasWidth, canvasHeight, lineSegments, vertices, 2 * segmentIndex + 1)
);
distance = Math.min (distance, SegmentPointDistance2D (segment, screenPoint));
}
return distance;
}

View File

@ -1,8 +1,10 @@
import { RGBColor } from '../model/color.js';
import { ConvertColorToThreeColor, DisposeThreeObjects } from '../threejs/threeutils.js';
import { ConvertColorToThreeColor, DisposeThreeObjects, GetLineSegmentsProjectedDistance } from '../threejs/threeutils.js';
import * as THREE from 'three';
const LineThresholdInPixels = 10.0;
export const IntersectionMode =
{
MeshOnly : 1,
@ -127,7 +129,6 @@ export class ViewerMainModel
this.edgeSettings = new EdgeSettings (false, new RGBColor (0, 0, 0), 1);
this.hasLines = false;
this.hasPolygonOffset = false;
this.fullBoundingBox = null;
}
SetMainObject (mainObject)
@ -135,7 +136,6 @@ export class ViewerMainModel
this.mainModel.SetRootObject (mainObject);
this.hasLines = false;
this.hasPolygonOffset = false;
this.fullBoundingBox = null;
this.EnumerateLines ((line) => {
this.hasLines = true;
@ -200,17 +200,6 @@ export class ViewerMainModel
this.UpdatePolygonOffset ();
}
GetFullBoundingBox ()
{
if (this.fullBoundingBox !== null) {
return this.fullBoundingBox;
}
this.fullBoundingBox = this.GetBoundingBox (() => {
return true;
});
return this.fullBoundingBox;
}
GetBoundingBox (needToProcess)
{
let hasMesh = false;
@ -311,18 +300,6 @@ export class ViewerMainModel
GetMeshIntersectionUnderMouse (intersectionMode, mouseCoords, camera, width, height)
{
function CalculateLineThreshold (mousePos, camera, boundingBoxCenter)
{
let thresholdInScreenCoordinates = 15.0;
let frustumRange = camera.far - camera.near;
let cameraDistanceFromCenter = boundingBoxCenter.distanceTo (camera.position);
let distanceInFrustumRatio = cameraDistanceFromCenter / frustumRange;
let zValue = -1.0 + 2.0 * distanceInFrustumRatio;
let referencePoint1 = new THREE.Vector3 (mousePos.x, mousePos.y, zValue).unproject (camera);
let referencePoint2 = new THREE.Vector3 (mousePos.x + thresholdInScreenCoordinates, mousePos.y, zValue).unproject (camera);
return referencePoint1.distanceTo (referencePoint2);
}
if (this.mainModel.IsEmpty ()) {
return null;
}
@ -336,16 +313,9 @@ export class ViewerMainModel
mousePos.y = -(mouseCoords.y / height) * 2 + 1;
let raycaster = new THREE.Raycaster ();
if (this.hasLines) {
let boundingBox = this.GetFullBoundingBox ();
if (boundingBox !== null) {
let boundingBoxCenter = new THREE.Vector3 (0.0, 0.0, 0.0);
boundingBox.getCenter (boundingBoxCenter);
raycaster.params.Line.threshold = CalculateLineThreshold (mousePos, camera, boundingBoxCenter);
}
}
raycaster.setFromCamera (mousePos, camera);
raycaster.params.Line.threshold = 10.0;
let iSectObjects = raycaster.intersectObject (this.mainModel.GetRootObject (), true);
for (let i = 0; i < iSectObjects.length; i++) {
let iSectObject = iSectObjects[i];
@ -355,7 +325,13 @@ export class ViewerMainModel
if (intersectionMode === IntersectionMode.MeshOnly && iSectObject.object.isLineSegments) {
continue;
}
if (iSectObject.object.isMesh || iSectObject.object.isLineSegments) {
if (iSectObject.object.isMesh) {
return iSectObject;
} else if (iSectObject.object.isLineSegments) {
let distance = GetLineSegmentsProjectedDistance (camera, width, height, iSectObject.object, mouseCoords);
if (distance > LineThresholdInPixels) {
continue;
}
return iSectObject;
}
}