//Assumes the following pipeline:
        // 1: ColorMesh outputted from Kinect API
        // 2: ColorMesh turned into CVMesh by KinectFusionizer
        // 3: No further edits have been made
        public CVMesh Slice(CVMesh meshIn, double y_min, double y_max, bool inverted = true)
        {
            if (y_min >= y_max)
            {
                throw new Exception("Minimum value must be lower than maximum value");
            }
            if (meshIn == null)
            {
                throw new Exception("Mesh is null");
            }
            if (meshIn.Vertices.Count == 0)
            {
                throw new Exception("Mesh has no vertices");
            }
            CVMesh meshOut = CVMesh.Clone(meshIn);

            //the depth image is flipped in comparison to output image
            if (inverted)
            {
                double yMinTemp = y_min;
                y_min  = y_max;
                y_max  = yMinTemp;
                y_min *= -1;
                y_max *= -1;
            }
            yMin = y_min;
            yMax = y_max;
            //only add the same vector if it is unique. the vector itself is the key.
            //the value is the original index the vector had
            meshOut.Faces = Extensions.ToFaces(meshOut.TriangleIndeces);
            meshOut       = RemoveNonSurfaceFaces(meshOut);
            Dictionary <Vector3, int> uniques         = new Dictionary <Vector3, int>();
            Dictionary <int, int>     oldToNewIndices = new Dictionary <int, int>();
            //We can only delete something once, but multiple deleted vertices can
            //refer to one unique vertice, so:
            //Key = deleted, value = unique vertice
            Dictionary <int, int> deleted = new Dictionary <int, int>();

            SplitVertices(ref uniques, ref deleted, ref oldToNewIndices, meshOut.Vertices, meshOut);
            meshOut.Faces    = AssignFacesNewIndices(deleted, oldToNewIndices, meshOut.Faces);
            meshOut.Vertices = new List <Vector3>();
            foreach (var unique in uniques)
            {
                meshOut.Vertices.Add(unique.Key);
            }
            meshOut.TriangleIndeces = Extensions.ToTriangleIndices(meshOut.Faces);
            string location = Environment.CurrentDirectory;

            PLYHandler.Output(meshOut, ref location, false);
            return(meshOut);
        }
        /// <summary>
        /// Translates, rotates and scales a mesh from the 3D camera's view to the Robot Arm's view
        /// </summary>
        /// <param name="mesh">The mesh we wish to transform</param>
        /// <returns>A mesh in another space</returns>
        public CVMesh ConvertToRobospace(CVMesh mesh)
        {
            CVMesh         converted           = CVMesh.Clone(mesh);
            List <Vector3> vertices            = converted.Vertices;
            List <Vector3> transformedVertices = new List <Vector3>();

            foreach (var v in vertices)
            {
                Vector3 transformed = TransformVertex(v, TransformMatrix);
                transformedVertices.Add(transformed);
            }
            converted.Vertices = transformedVertices;

            return(converted);
        }