private static bool IsReallyACone(IEnumerable <PolygonalFace> facesAll, out double[] axis, out double coneAngle)
        {
            var faces = ListFunctions.FacesWithDistinctNormals(facesAll.ToList());
            var n     = faces.Count;

            if (faces.Count <= 1)
            {
                axis      = null;
                coneAngle = double.NaN;
                return(false);
            }
            if (faces.Count == 2)
            {
                axis      = faces[0].Normal.crossProduct(faces[1].Normal).normalize();
                coneAngle = 0.0;
                return(false);
            }

            // a simpler approach: if the cross product of the normals are all parallel, it's a cylinder,
            // otherwise, cone.

            /*var r = new Random();
             * var rndList = new List<int>();
             * var crossProd = new List<double[]>();
             * var c = 0;
             * while (c < 20)
             * {
             *  var ne = r.Next(facesAll.Count);
             *  if (!rndList.Contains(ne)) rndList.Add(ne);
             *  c++;
             * }
             * for (var i = 0; i < rndList.Count-1; i++)
             * {
             *  for (var j = i + 1; j < rndList.Count; j++)
             *  {
             *      crossProd.Add(facesAll[i].Normal.crossProduct(facesAll[j].Normal).normalize());
             *  }
             * }
             * axis = crossProd[0];
             * coneAngle = 0.0;
             * for (var i = 0; i < crossProd.Count - 1; i++)
             * {
             *  for (var j = i + 1; j < crossProd.Count; j++)
             *  {
             *      if (Math.Abs(crossProd[i].dotProduct(crossProd[j]) - 1) < 0.00000008) return true;
             *  }
             * }
             * return false;*/

            // find the plane that the normals live on in the Gauss sphere. If it is not
            // centered at 0 then you have a cone.
            // since the vectors that are the difference of two normals (v = n1 - n2) would
            // be in the plane, let's first figure out the average plane of this normal
            var inPlaneVectors = new double[n][];

            inPlaneVectors[0] = faces[0].Normal.subtract(faces[n - 1].Normal);
            for (int i = 1; i < n; i++)
            {
                inPlaneVectors[i] = faces[i].Normal.subtract(faces[i - 1].Normal);
            }

            var normalsOfGaussPlane = new List <double[]>();
            var tempCross           = inPlaneVectors[0].crossProduct(inPlaneVectors[n - 1]).normalize();

            if (!tempCross.Any(double.IsNaN))
            {
                normalsOfGaussPlane.Add(tempCross);
            }
            for (int i = 1; i < n; i++)
            {
                tempCross = inPlaneVectors[i].crossProduct(inPlaneVectors[i - 1]).normalize();
                if (!tempCross.Any(double.IsNaN))
                {
                    if (tempCross.dotProduct(normalsOfGaussPlane[0]) >= 0)
                    {
                        normalsOfGaussPlane.Add(tempCross);
                    }
                    else
                    {
                        normalsOfGaussPlane.Add(tempCross.multiply(-1));
                    }
                }
            }
            var normalOfGaussPlane = new double[3];

            normalOfGaussPlane = normalsOfGaussPlane.Aggregate(normalOfGaussPlane, (current, c) => current.add(c));
            normalOfGaussPlane = normalOfGaussPlane.divide(normalsOfGaussPlane.Count);

            var distance = faces.Sum(face => face.Normal.dotProduct(normalOfGaussPlane));

            if (distance < 0)
            {
                axis     = normalOfGaussPlane.multiply(-1);
                distance = -distance / n;
            }
            else
            {
                distance /= n;
                axis      = normalOfGaussPlane;
            }
            coneAngle = Math.Asin(distance);
            return(Math.Abs(distance) >= ClassificationConstants.MinConeGaussPlaneOffset);
        }
 private static bool IsReallyAFlat(IEnumerable <PolygonalFace> faces)
 {
     return(ListFunctions.FacesWithDistinctNormals(faces.ToList()).Count == 1);
 }