且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在Autodesk Forge Viewer中的元素下进行拾取

更新时间:2023-01-06 13:06:47

基于Zhong Wu在另一个

Based on the suggestion of Zhong Wu in another post, here is the final solution to select element which is under or inside another element. I created an Autodesk Forge viewer extension to use it easily.

///////////////////////////////////////////////////////////////////////////////
// InnerSelection viewer extension
// by Khoa Ho, December 2016
//
///////////////////////////////////////////////////////////////////////////////
AutodeskNamespace("Autodesk.ADN.Viewing.Extension");

Autodesk.ADN.Viewing.Extension.InnerSelection = function (viewer, options) {

    Autodesk.Viewing.Extension.call(this, viewer, options);

    var _self = this;

    var _container = viewer.canvas.parentElement;
    var _renderer = viewer.impl.renderer();
    var _instanceTree = viewer.model.getData().instanceTree;
    var _fragmentList = viewer.model.getFragmentList();
    var _eventSelectionChanged = false;
    var _viewport;
    var _outerDbId;

    _self.load = function () {

        _container.addEventListener('mousedown',
            onMouseDown);

        viewer.addEventListener(
            Autodesk.Viewing.SELECTION_CHANGED_EVENT,
            onItemSelected);

        console.log('Autodesk.ADN.Viewing.Extension.InnerSelection loaded');

        return true;
    };

    _self.unload = function () {

        _container.removeEventListener('mousedown',
            onMouseDown);

        viewer.removeEventListener(
            Autodesk.Viewing.SELECTION_CHANGED_EVENT,
            onItemSelected);

        console.log('Autodesk.ADN.Viewing.Extension.InnerSelection unloaded');

        return true;
    };

    function onMouseDown(e) {

        var viewport = viewer.impl.clientToViewport(e.canvasX, e.canvasY);
        _viewport = viewport; // Keep this viewport to use in onItemSelected()

        var dbId = _renderer.idAtPixel(viewport.x, viewport.y);

        if (_outerDbId == dbId) {
            _outerDbId = -1;

            // Deselect everything
            viewer.select();
        } else {
            _outerDbId = dbId;

            // Hide outer element temporarily to allow picking its behind element
            viewer.hideById(dbId);

            _eventSelectionChanged = true;
        }

        viewer.impl.sceneUpdated(true);
    }

    function onItemSelected(e) {

        if (_eventSelectionChanged) {

            // Prevent self looping on selection
            _eventSelectionChanged = false;

            // Show outer element back
            viewer.show(_outerDbId);

            // Get inner element Id after the outer element
            // was just hidden on mouse down event
            var innerDbId = _renderer.idAtPixel(_viewport.x, _viewport.y);

            if (innerDbId > -1) {
                // Select the inner element when it is found
                viewer.select(innerDbId);

                console.debug("Selected inner Id: " + innerDbId);

            } else if (_outerDbId > -1) {
                // Select the outer element if the inner element is not found
                viewer.select(_outerDbId);

                console.debug("Selected outer Id: " + _outerDbId);

            }
        }
    }

};

Autodesk.ADN.Viewing.Extension.InnerSelection.prototype =
    Object.create(Autodesk.Viewing.Extension.prototype);

Autodesk.ADN.Viewing.Extension.InnerSelection.prototype.constructor =
    Autodesk.ADN.Viewing.Extension.InnerSelection;

Autodesk.Viewing.theExtensionManager.registerExtension(
    'Autodesk.ADN.Viewing.Extension.InnerSelection',
    Autodesk.ADN.Viewing.Extension.InnerSelection);