internal override Rect CalculateSubgraphBoundsInnerSpace(bool renderBounds) { Camera camera = Camera; if (camera == null) { return(Rect.Empty); } // // Cache the 3D bounding box for future use. Here we are relying on // the fact that this method is called by PrecomputeContent(), // which is called prior to all usages of _bboxChildrenSubgraph3D. // _bboxChildrenSubgraph3D = ComputeSubgraphBounds3D(); if (_bboxChildrenSubgraph3D.IsEmpty) { // Attempting to project empty bounds will result in NaNs which // which will ruin descendant bounds for the 2D tree. We handle // this explicitly and early exit with the correct answer. return(Rect.Empty); } Rect viewport = Viewport; // Common Case: Viewport3DVisual in a collasped UIElement. if (viewport.IsEmpty) { // Creating a 3D homogenous space to 2D viewport space transform // with an empty rectangle will result in NaNs which ruin the // descendant bounds for the 2D tree. We handle this explicitly // and early exit with the correct answer. // // (See also Windows OS Bugs #1637618) return(Rect.Empty); } double aspectRatio = M3DUtil.GetAspectRatio(viewport.Size); Matrix3D viewProjMatrix = camera.GetViewMatrix() * camera.GetProjectionMatrix(aspectRatio); Rect projectedBounds2D = MILUtilities.ProjectBounds(ref viewProjMatrix, ref _bboxChildrenSubgraph3D); Matrix homoToLocal = M3DUtil.GetHomogeneousToViewportTransform(viewport); MatrixUtil.TransformRect(ref projectedBounds2D, ref homoToLocal); return(projectedBounds2D); }
internal Point WorldToViewport(Point4D point) { double aspectRatio = M3DUtil.GetAspectRatio(Viewport.Size); Camera camera = Camera; if (camera != null) { Matrix3D viewProjMatrix = camera.GetViewMatrix() * camera.GetProjectionMatrix(aspectRatio); point *= viewProjMatrix; Point point2D = new Point(point.X / point.W, point.Y / point.W); point2D *= M3DUtil.GetHomogeneousToViewportTransform(Viewport); return(point2D); } else { return(new Point(0, 0)); } }