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); }