Exemple #1
0
        /// <summary>
        /// Creates (or gets the) child gameobject
        /// </summary>
        void CreateOrGetChildObject()
        {
            // Ensure that the camera component is set if this gets called before reset
            _camera = GetComponent <Camera>();

            // If there is a child gameobject named CameraFixedGradientSky...
            if (transform.Find("CameraFixedGradientSky") != null)
            {
                // Set it as the childObject
                childObject = transform.Find("CameraFixedGradientSky").gameObject;
            }
            else
            {
                // Otherwise - create a new gameobject
                childObject = new GameObject();

                // Set the name of the object - this is used when the object is destroyed so the name is important
                childObject.name = "CameraFixedGradientSky";

                // Set the parent of the transform to the camera transform
                childObject.transform.parent = transform;

                // Reset the local rotation so it's "zero"
                childObject.transform.localRotation = Quaternion.identity;

                // Hide the child gameobject in the inspector - we don't need to see it there
                childObject.hideFlags = HideFlags.HideInHierarchy;

                // Place the gameobject just behind the near clipping plane or in front of the far clipping plane
                if (placeAtClippingPlane == ClippingPlane.NEAR)
                {
                    childObject.transform.localPosition = new Vector3(0, 0, _camera.nearClipPlane + 0.01f);
                }
                else
                {
                    childObject.transform.localPosition = new Vector3(0, 0, _camera.farClipPlane - 0.01f);
                }

                // Add MeshFilter and MeshRenderer components to the child gameobject
                childObject.AddComponent <MeshFilter>();
                childObject.AddComponent <MeshRenderer>();

                // Create a MeshRenderer for the childObject
                CreateMeshRenderer(childObject.transform);

                // Set the Material to the shader with ZWrite off and RenderQueue set to Gemetry-1000 to ensure it's always rendered as a background
                Material _material = new Material(Shader.Find("Custom/VertexColorCamera"));
                childObject.GetComponent <MeshRenderer>().sharedMaterial = _material;
            }

            // Set the cached clipping plane to the clipping plane used so we can compare if it's changed
            _cacheClippingPlane = placeAtClippingPlane;

            // Create the gradient mesh and sett it to the sharedMesh for the MeshFilter
            childObject.GetComponent <MeshFilter>().sharedMesh = CreateMesh();

            // Set the mesh local scale to ensure it fills the camera based on its position and camera field of view and size
            SetMeshLocalScale();
        }
Exemple #2
0
        private static Vertex CreateTexturedVertex(ClippingPlane plane, Vector point, int width, int height)
        {
            double yzr = Vector.DotProduct(new Vector(1, 0, 0), plane.Normal);
            double xzr = Vector.DotProduct(new Vector(0, 1, 0), plane.Normal);
            double xyr = Vector.DotProduct(new Vector(0, 0, 1), plane.Normal);
            double yz  = Math.Abs(yzr);
            double xz  = Math.Abs(xzr);
            double xy  = Math.Abs(xyr);

            double rad  = Math.PI / 180 * -plane.Texture.Rotation;
            double crot = Math.Cos(rad);
            double srot = Math.Sin(rad);

            double xOffset = plane.Texture.OffsetX;
            double yOffset = plane.Texture.OffsetY;

            double x;
            double y;

            if (yz >= xz && yz >= xy)
            {
                x = -point.Y;
                y = point.Z;
            }
            else if (xz >= xy)
            {
                x = -point.X;
                y = point.Z;
            }
            else
            {
                x       = point.X;
                y       = point.Y;
                xOffset = -xOffset;
            }

            x /= -plane.Texture.ScaleX;
            y /= -plane.Texture.ScaleY;

            x = Math.Round(x);
            y = Math.Round(y);

            double a = x;
            double b = y;

            x = (crot * a) + (srot * b);
            y = -(srot * a) + (crot * b);

            x -= xOffset;
            y -= yOffset;

            double u = x / width;
            double v = y / height;

            return(new Vertex(point.X, point.Y, point.Z, u, v));
        }
Exemple #3
0
        private static clipping_plane GetViewpointClippingPlane(ClippingPlane GivenClippingPlane)
        {
            var ReturnObject = new clipping_plane();

            ReturnObject.direction   = new PointOrVector();
            ReturnObject.direction.x = GivenClippingPlane.Direction.X;
            ReturnObject.direction.y = GivenClippingPlane.Direction.Y;
            ReturnObject.direction.z = GivenClippingPlane.Direction.Z;
            ReturnObject.location    = new PointOrVector();
            ReturnObject.location.x  = GivenClippingPlane.Location.X;
            ReturnObject.location.y  = GivenClippingPlane.Location.Y;
            ReturnObject.location.z  = GivenClippingPlane.Location.Z;
            return(ReturnObject);
        }
Exemple #4
0
        private static Face ApplyTextures(Face face, ClippingPlane plane)
        {
            (int width, int height) = TextureFinder.FindSize(face.Texture);

            if (width == 0 || height == 0)
            {
                return(face);
            }

            Vector[] vectors = face.Vertices.ToArray();

            Vertex v1 = CreateTexturedVertex(plane, vectors[0], width, height);
            Vertex v2 = CreateTexturedVertex(plane, vectors[1], width, height);
            Vertex v3 = CreateTexturedVertex(plane, vectors[2], width, height);

            return(new Face(v1, v2, v3, face.Texture));
        }
Exemple #5
0
        /// <summary>
        /// Create a list of all intersection points of each set of three clipping planes.
        /// </summary>
        /// <param name="planes">The planes.</param>
        /// <returns>Gets all intersections of the given planes.</returns>
        private static IEnumerable <Vector> FindIntersections(IEnumerable <ClippingPlane> planes)
        {
            List <Vector> intersections = new List <Vector>();

            // Check every unique combination of three clipping planes and see if we can find an intersection point.
            int i = 0;

            foreach (ClippingPlane planeI in planes)
            {
                int j = ++i;
                foreach (ClippingPlane planeJ in planes.Skip(j))
                {
                    foreach (ClippingPlane planeK in planes.Skip(++j))
                    {
                        if (ClippingPlane.FindIntersection(planeI, planeJ, planeK, out Vector? intersection))
                        {
                            // Checks if there does not exist a clipping plane with which we are in front.
                            // Would result in vertices being added outside of our object.
                            bool rightSide = true;
                            foreach (ClippingPlane planeL in planes)
                            {
                                if (planeL != planeI && planeL != planeJ && planeL != planeK)
                                {
                                    double dot = Vector.DotProduct(intersection !, planeL.Normal) - planeL.D;
                                    if (dot > 0)
                                    {
                                        rightSide = false;
                                        break;
                                    }
                                }
                            }

                            if (rightSide && !intersections.Contains(intersection !))
                            {
                                intersections.Add(intersection !);
                            }
                        }
                    }
                }
            }

            return(intersections);
        }
Exemple #6
0
    /// <summary>
    /// Initialization function for the VolumeController. Ensures that the global variables needed by other objects are initialized first.
    /// </summary>
    private void Awake()
    {
        // 0. Create the data volume and its rendering material. This initialized the volume.
        currentVolume = new Volume(dataPath + volumeName + "/", "metadata.json");

        controller.VolName = volumeName;


        // 1. Set up the transfer function
        int isovalueRange = currentVolume.calculateIsovalueRange();

        transferFunction = new TransferFunction(isovalueRange);

        // 2. Set up the clipping plane
        clippingPlane = new ClippingPlane(new Vector3(0, 0, 0), new Vector3(1, 0, 0), false);
        updateClippingPlaneAll();

        // 3. Set up the target for the camera controls
        CameraControls cameraControls = (CameraControls)mainCamera.GetComponent(typeof(CameraControls));

        cameraControls.target = currentVolume.VolumeCube;

        //4. Initialize data packing.
        // Moved to update().


        // 5.  Unbound the framerate of this application
        Application.targetFrameRate = -1;

        // 6. Turn off v-sync
        QualitySettings.vSyncCount = 0;

        // DEBUG: Creating a wireframe bounding box cube
        if (drawBoundingBox)
        {
            boundingBoxLine = createBoundingBoxLineRenderer();
            Debug.Log("Trying to draw bounding box" + boundingBoxLine);
        }
    }
Exemple #7
0
    /// <summary>
    /// Initialization function for the VolumeController. Ensures that the global variables needed by other objects are initialized first.
    /// </summary>
    private void Awake()
    {
        // 0. Create the data volume and its rendering material
        currentVolume = new Volume(dataPath, "metadata.json");

        // 1. Set up the transfer function
        int isovalueRange = currentVolume.calculateIsovalueRange();

        transferFunction = new TransferFunction(isovalueRange);

        // 2. Set up the clipping plane
        clippingPlane = new ClippingPlane(new Vector3(0, 0, 0), new Vector3(1, 0, 0), false);
        updateClippingPlaneAll();

        // 3. Set up the target for the camera controls
        CameraControls cameraControls = (CameraControls)mainCamera.GetComponent(typeof(CameraControls));

        cameraControls.target = currentVolume.VolumeCube;

        // DEBUG: Creating a wireframe bounding box cube
        if (drawBoundingBox)
        {
            boundingBoxLine = createBoundingBoxLineRenderer();
        }

        // DEBUG: Create a box for the plane
        //clippingPlaneCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        //clippingPlaneCube.transform.position = clippingPlane.Position;
        //clippingPlaneCube.GetComponent<Renderer>().material = new Material(Shader.Find("Standard"));
        //clippingPlaneCube.transform.position = clippingPlane.Position;
        //clippingPlaneCube.transform.localScale = new Vector3(2.1f, 2.1f, 0.01f);
        //clippingPlaneCube.transform.rotation = Quaternion.LookRotation(clippingPlane.Normal);

        // Load the compute shader kernel
        analysisKernelID = brickAnalysisShader.FindKernel("BrickAnalysis");
    }
Exemple #8
0
        public static ClippingPlane[] GetClippingPlanesFromBoundingBox(XYZ max, XYZ min, Transform toMdoelSpaceTransform, Document doc)
        {
            List <ClippingPlane> clippingPlanes = new List <ClippingPlane>();

            // transform six normals to model coordinates and shared coordinates
#if REVIT2019
            ProjectPosition projectPosition = doc.ActiveProjectLocation.GetProjectPosition(XYZ.Zero);
#else
            ProjectPosition projectPosition = doc.ActiveProjectLocation.get_ProjectPosition(XYZ.Zero);
#endif
            Transform t1 = Transform.CreateTranslation(new XYZ(projectPosition.EastWest, projectPosition.NorthSouth, projectPosition.Elevation));
            Transform t2 = Transform.CreateRotation(XYZ.BasisZ, projectPosition.Angle);

            XYZ xPositiveNormalTransformed = t1.OfVector(t2.OfVector(toMdoelSpaceTransform.OfVector(new XYZ(1, 0, 0))));
            XYZ yPositiveNormalTransformed = t1.OfVector(t2.OfVector(toMdoelSpaceTransform.OfVector(new XYZ(0, 1, 0))));
            XYZ zPositiveNormalTransformed = t1.OfVector(t2.OfVector(toMdoelSpaceTransform.OfVector(new XYZ(0, 0, 1))));
            XYZ xNegativeNormalTransformed = t1.OfVector(t2.OfVector(toMdoelSpaceTransform.OfVector(new XYZ(-1, 0, 0))));
            XYZ yNegativeNormalTransformed = t1.OfVector(t2.OfVector(toMdoelSpaceTransform.OfVector(new XYZ(0, -1, 0))));
            XYZ zNegativeNormalTransformed = t1.OfVector(t2.OfVector(toMdoelSpaceTransform.OfVector(new XYZ(0, 0, -1))));

            // generate BCF clipping planes
            ClippingPlane xPositive = new ClippingPlane()
            {
                Direction = new Direction()
                {
                    X = xPositiveNormalTransformed.X, Y = xPositiveNormalTransformed.Y, Z = xPositiveNormalTransformed.Z
                },
                Location = new ARUP.IssueTracker.Classes.BCF2.Point()
                {
                    X = max.X, Y = max.Y, Z = max.Z
                }
            };

            ClippingPlane yPositive = new ClippingPlane()
            {
                Direction = new Direction()
                {
                    X = yPositiveNormalTransformed.X, Y = yPositiveNormalTransformed.Y, Z = yPositiveNormalTransformed.Z
                },
                Location = new ARUP.IssueTracker.Classes.BCF2.Point()
                {
                    X = max.X, Y = max.Y, Z = max.Z
                }
            };

            ClippingPlane zPositive = new ClippingPlane()
            {
                Direction = new Direction()
                {
                    X = zPositiveNormalTransformed.X, Y = zPositiveNormalTransformed.Y, Z = zPositiveNormalTransformed.Z
                },
                Location = new ARUP.IssueTracker.Classes.BCF2.Point()
                {
                    X = max.X, Y = max.Y, Z = max.Z
                }
            };

            ClippingPlane xNegative = new ClippingPlane()
            {
                Direction = new Direction()
                {
                    X = xNegativeNormalTransformed.X, Y = xNegativeNormalTransformed.Y, Z = xNegativeNormalTransformed.Z
                },
                Location = new ARUP.IssueTracker.Classes.BCF2.Point()
                {
                    X = min.X, Y = min.Y, Z = min.Z
                }
            };

            ClippingPlane yNegative = new ClippingPlane()
            {
                Direction = new Direction()
                {
                    X = yNegativeNormalTransformed.X, Y = yNegativeNormalTransformed.Y, Z = yNegativeNormalTransformed.Z
                },
                Location = new ARUP.IssueTracker.Classes.BCF2.Point()
                {
                    X = min.X, Y = min.Y, Z = min.Z
                }
            };

            ClippingPlane zNegative = new ClippingPlane()
            {
                Direction = new Direction()
                {
                    X = zNegativeNormalTransformed.X, Y = zNegativeNormalTransformed.Y, Z = zNegativeNormalTransformed.Z
                },
                Location = new ARUP.IssueTracker.Classes.BCF2.Point()
                {
                    X = min.X, Y = min.Y, Z = min.Z
                }
            };

            clippingPlanes.Add(xPositive);
            clippingPlanes.Add(yPositive);
            clippingPlanes.Add(zPositive);
            clippingPlanes.Add(xNegative);
            clippingPlanes.Add(yNegative);
            clippingPlanes.Add(zNegative);

            return(clippingPlanes.ToArray());
        }
Exemple #9
0
        /// <summary>
        /// Calculate the max point and the min point of Revit section box based on BCF clipping planes
        /// </summary>
        /// <param name="clippingPlanes">clipping planes from BCF viewpoint</param>
        /// <returns>1: max, 2: min</returns>
        private Tuple <BoundingBoxXYZ, Transform> getBoundingBoxFromClippingPlanes(Document doc, ClippingPlane[] clippingPlanes)
        {
            const double tolerance = 0.0000001;

            if (clippingPlanes.Count() != 6)
            {
                return(null);
            }

            try
            {
                List <ClippingPlane> cPlanes = clippingPlanes.ToList();
                double maxZ, minZ;

                // checking z direction normals
                List <XYZ>           zPoints           = new List <XYZ>();
                List <ClippingPlane> xyClipppingPlanes = new List <ClippingPlane>();
                foreach (ClippingPlane cp in cPlanes)
                {
                    XYZ zDirection = new XYZ(0, 0, 1);
                    XYZ normal     = new XYZ(cp.Direction.X, cp.Direction.Y, cp.Direction.Z);
                    if (normal.IsAlmostEqualTo(zDirection, tolerance) || normal.IsAlmostEqualTo(-zDirection, tolerance))
                    {
                        zPoints.Add(new XYZ(cp.Location.X, cp.Location.Y, cp.Location.Z));
                    }
                    else
                    {
                        xyClipppingPlanes.Add(cp);
                    }
                }
                if (zPoints.Count != 2)
                {
                    return(null);
                }
                else
                {
                    maxZ = zPoints[0].Z > zPoints[1].Z ? zPoints[0].Z : zPoints[1].Z;
                    minZ = zPoints[0].Z < zPoints[1].Z ? zPoints[0].Z : zPoints[1].Z;
                    maxZ = UnitUtils.ConvertToInternalUnits(maxZ, DisplayUnitType.DUT_METERS);
                    minZ = UnitUtils.ConvertToInternalUnits(minZ, DisplayUnitType.DUT_METERS);
                }

                // check if the remaining 4 points are on XY plane
                //if (!xyClipppingPlanes.TrueForAll(cp => (cp.Location.Z < tolerance && cp.Location.Z > -tolerance)))
                //{
                //    return null;
                //}

                // find out lines orthorgonal to self-normal
                List <Autodesk.Revit.DB.Line> linesToBeIntersected = new List <Autodesk.Revit.DB.Line>();
                foreach (ClippingPlane cp in xyClipppingPlanes)
                {
                    XYZ           planeNormal     = new XYZ(cp.Direction.X, cp.Direction.Y, cp.Direction.Z);
                    ClippingPlane othorgonalPlane = xyClipppingPlanes.Find(c => !(
                                                                               new XYZ(c.Direction.X, c.Direction.Y, c.Direction.Z).IsAlmostEqualTo(planeNormal, tolerance)
                                                                               ||
                                                                               new XYZ(c.Direction.X, c.Direction.Y, c.Direction.Z).IsAlmostEqualTo(-planeNormal, tolerance)
                                                                               ));
                    XYZ othorgonalNormal = new XYZ(othorgonalPlane.Direction.X, othorgonalPlane.Direction.Y, othorgonalPlane.Direction.Z);
                    XYZ planeOrigin      = new XYZ(cp.Location.X, cp.Location.Y, 0);

                    linesToBeIntersected.Add(Autodesk.Revit.DB.Line.CreateUnbound(planeOrigin, othorgonalNormal));
                }

                // get intersection results
                List <XYZ> intersectedPoints = new List <XYZ>();
                foreach (Autodesk.Revit.DB.Line line1 in linesToBeIntersected)
                {
                    foreach (Autodesk.Revit.DB.Line line2 in linesToBeIntersected)
                    {
                        if (line1 != line2)
                        {
                            // calculate intersection points
                            double a1 = line1.Direction.Y;
                            double b1 = line1.Direction.X;
                            double a2 = line2.Direction.Y;
                            double b2 = line2.Direction.X;

                            // if not parallel
                            double delta = b1 * a2 - a1 * b2;
                            if (delta > tolerance || delta < -tolerance)
                            {
                                double c1 = a1 * line1.Origin.X - b1 * line1.Origin.Y;
                                double c2 = a2 * line2.Origin.X - b2 * line2.Origin.Y;

                                double deltaX = b1 * c2 - b2 * c1;
                                double deltaY = a1 * c2 - a2 * c1;

                                double intersectionX = deltaX / delta;
                                double intersectionY = deltaY / delta;
                                intersectedPoints.Add(new XYZ(intersectionX, intersectionY, 0));
                            }
                        }
                    }
                }

                // find rightmost, leftmost, topmost, and bottommost points
                XYZ rightmost  = intersectedPoints[0];
                XYZ leftmost   = intersectedPoints[0];
                XYZ topmost    = intersectedPoints[0];
                XYZ bottommost = intersectedPoints[0]; // for non-rotated section box only
                if (intersectedPoints.Count < 4)
                {
                    return(null);
                }
                else
                {
                    foreach (XYZ p in intersectedPoints)
                    {
                        if (p.X > rightmost.X)
                        {
                            rightmost = p;
                        }
                        if (p.X < leftmost.X)
                        {
                            leftmost = p;
                        }
                        if (p.Y > topmost.Y)
                        {
                            topmost = p;
                        }
                        if (p.Y < bottommost.Y)
                        {
                            bottommost = p;
                        }
                    }
                }

                // change the coordinate system from Project to Shared
                rightmost  = ConvertToInteranlAndSharedCoordinate(doc, rightmost);
                leftmost   = ConvertToInteranlAndSharedCoordinate(doc, leftmost);
                topmost    = ConvertToInteranlAndSharedCoordinate(doc, topmost);
                bottommost = ConvertToInteranlAndSharedCoordinate(doc, bottommost);

                // create diagonal and rotation vector
                XYZ horizontalBase = new XYZ(-1, 0, 0);
                Autodesk.Revit.DB.Line diagonal     = Autodesk.Revit.DB.Line.CreateBound(rightmost, leftmost);
                Autodesk.Revit.DB.Line rotationBase = !rightmost.IsAlmostEqualTo(topmost, tolerance) ?
                                                      Autodesk.Revit.DB.Line.CreateBound(rightmost, topmost) :
                                                      Autodesk.Revit.DB.Line.CreateUnbound(new XYZ(0, 0, 0), horizontalBase);

                // return these two guys
                BoundingBoxXYZ bBox = new BoundingBoxXYZ();
                Transform      originalTransform = null;

                // compute a correct section box depending on two conditions
                if (rightmost.IsAlmostEqualTo(topmost, tolerance) ||
                    leftmost.IsAlmostEqualTo(bottommost, tolerance) ||
                    horizontalBase.IsAlmostEqualTo(rotationBase.Direction, tolerance) ||
                    horizontalBase.IsAlmostEqualTo(-rotationBase.Direction, tolerance))
                {  //non-rotated section box
                    XYZ max = new XYZ(
                        rightmost.X,
                        topmost.Y,
                        maxZ
                        );
                    XYZ min = new XYZ(
                        leftmost.X,
                        bottommost.Y,
                        minZ
                        );

                    bBox.Max = max;
                    bBox.Min = min;
                }
                else //rotated section box
                {
                    // calculate rotation angle
                    double angle = horizontalBase.AngleTo(rotationBase.Direction);

                    // create transform
                    Transform transform = Transform.CreateRotationAtPoint(new XYZ(0, 0, 1), angle, rightmost);

                    // rotate it then get the rotated bounding box projection point (i.e., min. of rorated section box)
                    XYZ rotatedMin = diagonal.CreateTransformed(transform).GetEndPoint(1);

                    // create rotated section box with max and min
                    XYZ max = new XYZ(
                        rightmost.X,
                        rightmost.Y,
                        maxZ
                        );
                    XYZ min = new XYZ(
                        rotatedMin.X,
                        rotatedMin.Y,
                        minZ
                        );

                    bBox.Max = max;
                    bBox.Min = min;

                    // rotate back to the original position
                    originalTransform = Transform.CreateRotationAtPoint(new XYZ(0, 0, 1), -angle, max);
                }

                return(new Tuple <BoundingBoxXYZ, Transform>(bBox, originalTransform));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return(null);
            }
        }
Exemple #10
0
 private void Awake()
 {
     instance = this;
     matList  = new List <Material>();
 }
Exemple #11
0
        /// <summary>
        /// Generate Viewpoint
        /// </summary>
        private VisualizationInfo generateViewpoint()
        {
            try
            {
                // save selected elements to BCF compoments first
                List <Component> bcfComponents = new List <Component>();
                var selectedElements           = MSApp.ActiveModelReference.GetSelectedElements().BuildArrayFromContents();
                if (selectedElements.Length > 0)
                {
                    string originatingSystem = getBentleyProductName();
                    bcfComponents = new List <Component>();
                    foreach (Element e in selectedElements)
                    {
                        string          ifcGuid = string.Empty;
                        PropertyHandler handler = MSApp.CreatePropertyHandler(e);
                        if (handler.SelectByAccessString("GUID"))
                        {
                            Guid guid = parseGuid(handler.GetDisplayString());
                            ifcGuid = IfcGuid.ToIfcGuid(guid).ToString();
                        }
                        bcfComponents.Add(new Component(originatingSystem, e.ID.ToString(), ifcGuid));
                    }
                }

                // get current view
                int    activeViewNum = getActiveViewNumber();
                View   currentView   = MSApp.ActiveDesignFile.Views[activeViewNum];
                double unitFactor    = 1 / GetGunits();

                // enable perspective camera back and forth to get correct view attributes, see the post below
                // https://communities.bentley.com/products/programming/microstation_programming/f/343173/t/80064
                MSApp.CadInputQueue.SendKeyin("MDL KEYIN BENTLEY.VIEWATTRIBUTESDIALOG,VAD VIEWATTRIBUTESDIALOG SETATTRIBUTE 0 Camera True");
                MSApp.CadInputQueue.SendKeyin("MDL KEYIN BENTLEY.VIEWATTRIBUTESDIALOG,VAD VIEWATTRIBUTESDIALOG SETATTRIBUTE 0 Camera False");

                // camera direction
                Point3d direction = MSApp.Point3dNormalize(MSApp.Point3dSubtract(currentView.get_CameraTarget(), currentView.get_CameraPosition()));

                // force view center to be identical as camera target if camera direction is not along Z axis (i.e., not top view or bottom view)
                if (direction.X > distancePrecision || direction.Y > distancePrecision) // arbitrary precision
                {
                    Point3d center = new Point3d();
                    center = currentView.get_Center();
                    Point3d extents = new Point3d();
                    extents = currentView.get_Extents();
                    Point3d translation = new Point3d();
                    translation = MSApp.Point3dSubtract(center, currentView.get_CameraTarget());
                    ViewCameraParameters vcp = new ViewCameraParametersClass();
                    vcp.set_CameraPosition(MSApp.Point3dAdd(currentView.get_CameraPosition(), translation));
                    vcp.set_CameraTarget(MSApp.Point3dAdd(currentView.get_CameraTarget(), translation));
                    currentView.SetCameraProperties(vcp);
                    currentView.set_Extents(extents);
                    currentView.set_Center(center);
                    currentView.Redraw();
                }

                // camera scale
                double h   = currentView.get_Extents().Y *unitFactor;
                double w   = currentView.get_Extents().X *unitFactor;
                double fov = 180 * currentView.CameraAngle / Math.PI;

                // camera location
                Point3d cameraLocation = MSApp.Point3dScale(currentView.get_CameraPosition(), unitFactor);
                // grab current view center point and force to top view if camera direction is along Z axis (i.e., top view or bottom view)
                if (direction.X < distancePrecision && direction.Y < distancePrecision) // arbitrary precision
                {
                    cameraLocation = MSApp.Point3dScale(currentView.get_Center(), unitFactor);
                    direction.Z    = -1.0;
                }

                // camera up vector
                Point3d upVector = currentView.get_CameraUpVector();

                // set up BCF viewpoint
                VisualizationInfo v = new VisualizationInfo();
                v.Components = bcfComponents;

                // FIXME: ignore perspective view for now

                /*if (currentView.isPerspective)
                 * {
                 *  v.PerspectiveCamera = new PerspectiveCamera();
                 *  v.PerspectiveCamera.CameraViewPoint.X = cameraLocation.X;
                 *  v.PerspectiveCamera.CameraViewPoint.Y = cameraLocation.Y;
                 *  v.PerspectiveCamera.CameraViewPoint.Z = cameraLocation.Z;
                 *  v.PerspectiveCamera.CameraUpVector.X = upVector.X;
                 *  v.PerspectiveCamera.CameraUpVector.Y = upVector.Y;
                 *  v.PerspectiveCamera.CameraUpVector.Z = upVector.Z;
                 *  v.PerspectiveCamera.CameraDirection.X = direction.X;
                 *  v.PerspectiveCamera.CameraDirection.Y = direction.Y;
                 *  v.PerspectiveCamera.CameraDirection.Z = direction.Z;
                 *  v.PerspectiveCamera.FieldOfView = fov;
                 * }
                 * else
                 * {*/
                v.OrthogonalCamera = new OrthogonalCamera();
                v.OrthogonalCamera.CameraViewPoint.X = cameraLocation.X;
                v.OrthogonalCamera.CameraViewPoint.Y = cameraLocation.Y;
                v.OrthogonalCamera.CameraViewPoint.Z = cameraLocation.Z;
                v.OrthogonalCamera.CameraUpVector.X  = upVector.X;
                v.OrthogonalCamera.CameraUpVector.Y  = upVector.Y;
                v.OrthogonalCamera.CameraUpVector.Z  = upVector.Z;
                v.OrthogonalCamera.CameraDirection.X = direction.X;
                v.OrthogonalCamera.CameraDirection.Y = direction.Y;
                v.OrthogonalCamera.CameraDirection.Z = direction.Z;
                v.OrthogonalCamera.ViewToWorldScale  = h;
                //}

                // get current clip volume and compute clipping planes
                ulong previousClipVolumeId = 0;
                try
                {
                    int status = mdlView_getClipBoundaryElement(ref previousClipVolumeId, activeViewNum - 1).ToInt32();
                    if (status == 0)
                    {
                        Element previousClipVolume = MSApp.ActiveModelReference.GetElementByID((long)previousClipVolumeId);
                        var     smartSolids        = MSApp.SmartSolid.ConvertToSmartSolidElement(previousClipVolume).BuildArrayFromContents();
                        if (smartSolids.Length > 0)
                        {
                            // just consider one solid for now
                            SmartSolidElement clipVolumeSolid = smartSolids[0].AsSmartSolidElement;
                            var surfaces = clipVolumeSolid.ExtractAllSurfaceFromSolid().BuildArrayFromContents();
                            List <ClippingPlane> clippingPlanes = new List <ClippingPlane>();
                            foreach (Element surface in surfaces)
                            {
                                ComplexShapeElement surfaceShape = surface.AsComplexShapeElement();
                                var vertices = surfaceShape.ConstructVertexList(0.1); // arbitrary tolerance for now
                                if (vertices.Length > 0)
                                {
                                    // produce BCF clipping planes
                                    Point3d       location      = MSApp.Point3dScale(MSApp.Point3dAdd(clipVolumeSolid.Origin, vertices[0]), unitFactor);
                                    ClippingPlane clippingPlane = new ClippingPlane()
                                    {
                                        Direction = new Direction()
                                        {
                                            X = surfaceShape.Normal.X, Y = surfaceShape.Normal.Y, Z = surfaceShape.Normal.Z
                                        },
                                        Location = new Classes.BCF2.Point()
                                        {
                                            X = location.X, Y = location.Y, Z = location.Z
                                        }
                                    };
                                    clippingPlanes.Add(clippingPlane);
                                }
                            }
                            // add to BCF clipping planes
                            v.ClippingPlanes = clippingPlanes.ToArray();
                        }
                    }
                }
                catch (Exception ex)
                {
                    // do nothing just for catching the exception when clip volume not found, element not found, or not being converted to smart solid
                }

                return(v);
            }
            catch (System.Exception ex1)
            {
                MessageBox.Show("exception: " + ex1, "Error!");
            }
            return(null);
        }