static bool TryGetPipe(Solid3d solid, out Pipe pipe)
{
using (var brep
= new Brep
(solid
)) {
// must have 4 edges
var edges = brep.Edges;
if (edges.Count() != 4)
return false;
// all eges must be circular or elliptical
var externalCurves = edges.Select(e => (ExternalCurve3d)e.Curve);
if (!externalCurves.All(c => c.IsCircularArc || c.IsEllipticalArc))
return false;
var nativeCurves = externalCurves.Select(c => c.NativeCurve).ToArray();
// must have 2 distinct centers
var pointComparer
= new PointComparer
(); var centers = nativeCurves
.Select(c
=> c
is CircularArc3d
? ((CircularArc3d
)c
).Center : ((EllipticalArc3d
)c
).Center) .Distinct(pointComparer)
.ToArray();
if (centers.Length != 2)
return false;
double length = centers[0].DistanceTo(centers[1]);
// must have 2 distinct radii
var doubleComprer
= new DoubleComparer
(); var radii = nativeCurves
.Select(c
=> c
is CircularArc3d
? ((CircularArc3d
)c
).Radius : ((EllipticalArc3d
)c
).MinorRadius) .Distinct(doubleComprer)
.ToArray();
if (radii.Length != 2)
return false;
double radius = Math.Max(radii[0], radii[1]);
foreach (var group in nativeCurves
.OfType<EllipticalArc3d>()
.GroupBy(e => e.Center, pointComparer))
{
double majRad = group.Max(e => e.MajorRadius);
length += Math.Sqrt(majRad * majRad - radius * radius);
}
{
Diameter = radius * 2.0,
Direction = centers[0].GetVectorTo(centers[1]).GetNormal(),
Length = length,
Thickness = Math.Abs(radii[0] - radii[1])
};
return true;
}
}
struct Pipe
{
public double Diameter { get; set; }
public Vector3d Direction { get; set; }
public double Length { get; set; }
public double Thickness { get; set; }
}
class DoubleComparer : IEqualityComparer<double>
{
public bool Equals(double x, double y) =>
Math.Round(x, 9) == Math.Round(x, 9);
public int GetHashCode(double d) => Math.Round(d, 9).GetHashCode();
}
class PointComparer : IEqualityComparer<Point3d>
{
public bool Equals(Point3d x, Point3d y) =>
x
.IsEqualTo(y,
new Tolerance
(1e
-10, 1e
-9
)); public int GetHashCode(Point3d p) =>
new Point3d
(Math
.Round(p
.X,
9), Math
.Round(p
.Y,
9), Math
.Round(p
.Z,
9)).GetHashCode(); }