Beispiel #1
0
        private void ApplyViewOrientationAndVisibility(UIDocument uiDocument, View3D view, Camera camera)
        {
            using var trans = new Transaction(uiDocument.Document);
            if (trans.Start($"Apply view orientation and visibility in '{view.Name}'") != TransactionStatus.Started)
            {
                return;
            }

            StatusBarService.SetStatusText("Loading view point data ...");
            Log.Information("Calculating view orientation from camera position ...");
            ProjectPosition projectPosition   = uiDocument.Document.ActiveProjectLocation.GetProjectPosition(XYZ.Zero);
            var             viewOrientation3D = RevitUtils.TransformCameraPosition(
                new ProjectPositionWrapper(projectPosition),
                camera.Position.ToInternalUnits(),
                true)
                                                .ToViewOrientation3D();

            if (camera.Type == CameraType.Perspective)
            {
                Log.Information("Setting active far viewer bound to zero ...");
                Parameter farClip = view.get_Parameter(BuiltInParameter.VIEWER_BOUND_ACTIVE_FAR);
                if (farClip.HasValue)
                {
                    farClip.Set(0);
                }
            }

            Log.Information("Applying new view orientation ...");
            view.SetOrientation(viewOrientation3D);

            Log.Information("Applying element visibility ...");
            var currentlyVisibleElements = uiDocument.Document.GetVisibleElementsOfView(view);
            var map = uiDocument.Document.GetIfcGuidElementIdMap(currentlyVisibleElements);
            var exceptionElements = GetViewpointVisibilityExceptions(map);
            var selectedElements  = GetViewpointSelection(map);

            if (exceptionElements.Any())
            {
                if (_bcfViewpoint.GetVisibilityDefault())
                {
                    view.HideElementsTemporary(exceptionElements);
                    selectedElements = selectedElements.Where(id => !exceptionElements.Contains(id)).ToList();
                }
                else
                {
                    view.IsolateElementsTemporary(exceptionElements);
                    selectedElements = selectedElements.Where(id => exceptionElements.Contains(id)).ToList();
                }
            }

            view.ConvertTemporaryHideIsolateToPermanent();

            if (selectedElements.Any())
            {
                Log.Information("Select {n} elements ...", selectedElements.Count);
                uiDocument.Selection.SetElementIds(selectedElements);
            }

            trans.Commit();
        }
Beispiel #2
0
        /// <summary>
        /// Zoom the view to the correct scale, if necessary.
        /// </summary>
        /// <remarks>In Revit, orthogonal views do not change their camera positions, when zooming in or out. Hence,
        /// the values stored in the BCF viewpoint are not sufficient to restore the previously exported viewpoint.
        /// In order to get correct zooming, the scale value (view box height) is used, to calculate the correct zoom
        /// corners according to view center.
        /// See https://thebuildingcoder.typepad.com/blog/2020/10/save-and-restore-3d-view-camera-settings.html
        /// </remarks>
        private static void ZoomIfNeeded(UIApplication app, Camera camera, ElementId viewId)
        {
            if (camera.Type != CameraType.Orthogonal || camera is not OrthogonalCamera orthoCam)
            {
                return;
            }

            Log.Information("Found orthogonal camera, setting zoom callback ...");
            StatusBarService.SetStatusText("Waiting for view to render to apply zoom ...");
            AppIdlingCallbackListener.SetPendingZoomChangedCallback(app, viewId, orthoCam.ViewToWorldScale);
        }
        /// <summary>
        /// Sets a callback that applies a zoom to the current view.
        /// </summary>
        /// <param name="app">The current UI application.</param>
        /// <param name="viewId">The view ID for the view to be zoomed.</param>
        /// <param name="zoom">The zoom in decimal precision.</param>
        public static void SetPendingZoomChangedCallback(UIApplication app, ElementId viewId, decimal zoom)
        {
            void Callback(object sender, IdlingEventArgs args)
            {
                StatusBarService.SetStatusText("Zooming to scale '" + zoom + "' ...");
                UIView currentView = app.ActiveUIDocument.GetOpenUIViews().First();

                if (currentView.ViewId != viewId)
                {
                    return;
                }

                UIDocument uiDoc      = app.ActiveUIDocument;
                View       activeView = uiDoc.ActiveView;

                var zoomCorners = currentView.GetZoomCorners();
                XYZ bottomLeft  = zoomCorners[0];
                XYZ topRight    = zoomCorners[1];

                var(currentHeight, currentWidth) =
                    RevitUtils.ConvertToViewBoxValues(topRight, bottomLeft, activeView.RightDirection);

                var zoomedViewBoxHeight = Convert.ToDouble(zoom).ToInternalRevitUnit();
                var zoomedViewBoxWidth  = zoomedViewBoxHeight * currentWidth / currentHeight;

                XYZ newTopRight = activeView.Origin
                                  .Add(activeView.UpDirection.Multiply(zoomedViewBoxHeight / 2))
                                  .Add(activeView.RightDirection.Multiply(zoomedViewBoxWidth / 2));
                XYZ newBottomLeft = activeView.Origin
                                    .Subtract(activeView.UpDirection.Multiply(zoomedViewBoxHeight / 2))
                                    .Subtract(activeView.RightDirection.Multiply(zoomedViewBoxWidth / 2));

                Log.Information("Zoom to {topRight} | {bottomLeft} ...", newTopRight.ToString(), newBottomLeft.ToString());
                currentView.ZoomAndCenterRectangle(newTopRight, newBottomLeft);

                StatusBarService.ResetStatusBarText();
                Log.Information("Finished applying zoom for orthogonal view.");
                app.Idling -= Callback;
            }

            Log.Information("Append zoom callback for orthogonal view to idle state of Revit application ...");
            app.Idling += Callback;
        }