public static Surface ExtractSurface(Autodesk.Revit.DB.ConicalFace face, IEnumerable <PolyCurve> edgeLoops) { // Note: Internal representation of the cone // S(u, v) = Origin + v*[sin(HalfAngle)*(cos(u)*Radius[0] + sin(u)*Radius[1]) + cos(HalfAngle)*Axis] edgeLoops = edgeLoops.ToList(); // Get some data from the face var axis = face.Axis.ToVector(); var x = face.get_Radius(0).ToVector(); var y = face.get_Radius(1).ToVector(); var tipPt = face.Origin.ToPoint(); var ang = face.HalfAngle; // We use the max length in order to help find the lowest possible base point for the cone var maxLength = edgeLoops.Max(pc => pc.Length); // We don't know the "base" point of the cone, so we build it here // by projecting a point on the edge loops onto the axis var pt = edgeLoops.First().StartPoint; var dir = pt.Subtract(tipPt.AsVector()); var projLength = dir.AsVector().Dot(axis); var height = projLength + 2 * maxLength; var o = tipPt.Add(axis.Normalized().Scale(height)); // there's not an easy way to create a conical surface in protogeometry outside of this // note this coordinate system has the z axis reversed because we're building the cone // from it's flat bottom surface var baseCS = CoordinateSystem.ByOriginVectors(o, x, y.Reverse()); // Construct the radius var rad = Math.Cos(ang) * height; var cone = Cone.ByCoordinateSystemHeightRadius(baseCS, height, rad); // PB: this is iffy code - we need to extract the surface that's not touching the origin //return cone.Faces.Select(f => f.SurfaceGeometry()).First(s => s.DistanceTo(o) > 1e-5); // the flat face of the cone is currently the second face in the Faces enumeration return(cone.Faces[1].SurfaceGeometry()); }