hypar-io / Elements

The smallest useful BIM.
https://www.hypar.io
MIT License
349 stars 74 forks source link

Regression Elements.Geometry.Solids.Sweep #1007

Open pederlh opened 1 year ago

pederlh commented 1 year ago

Describe the bug From version 1.6.0 to 2.0.0, an exception is thrown when initializing some Sweep objects, in cases where possible earlier. A reproducible example is included below.

Test method HyparDebugging.GeometryTest.Sweepbug threw exception: 
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'The vector could not be created. One or more of the components was NaN.')
    Stack Trace:
        at Elements.Geometry.Vector3..ctor(Double x, Double y, Double z)
   at Elements.Geometry.Solids.Solid.ProjectEdgeAlong(Edge[] loop, Vector3 v, Plane p)
   at Elements.Geometry.Solids.Solid.SweepEdgesBetweenPlanes(Edge[] loop1, Vector3 v, Plane end)
   at Elements.Geometry.Solids.Solid.SweepEdges(Transform[] transforms, Edge[] openEdge)
   at Elements.Geometry.Solids.Solid.SweepFaceAlongCurve(Polygon perimeter, IList`1 holes, IBoundedCurve curve, Double startSetback, Double endSetback, Double profileRotation)
   at Elements.Geometry.Kernel.CreateSweepAlongCurve(Profile profile, BoundedCurve curve, Double startSetback, Double endSetback, Double profileRotation)
   at Elements.Geometry.Solids.Sweep.UpdateGeometry()
   at Elements.Geometry.Solids.Sweep..ctor(Profile profile, BoundedCurve curve, Double startSetback, Double endSetback, Double profileRotation, Boolean isVoid)

To Reproduce

// Works in version 1.6.0, not in 2.0.0

Polygon crossSection = Polygon.Rectangle(0.25, 0.25);

Polyline curve = new(new List<Vector3>
{
        new Vector3(x: 20.0, y: 15.0, z:0.0),
        new Vector3(x: 20.0, y: 15.0, z:1.0),
        new Vector3(x: 20.0, y: 14.5, z:1.5),
        new Vector3(x: 19.5, y: 14.5, z:1.5),
}
);

var sweep = new Elements.Geometry.Solids.Sweep(
    new Profile(crossSection),
    curve,
    startSetback: 1,
    endSetback: 1,
    profileRotation: 0,
    isVoid: false
);

Desktop (please complete the following information):

pederlh commented 1 year ago

Updated the MRE with a much simpler cross section polygon (previously Polygon crossSection = new Circle(radius: 0.25).ToPolygon(20);) and a sweep curve with fewer points.

DmytroMuravskyi commented 1 year ago

There is a bug related to setbacks. They are distance based, so with setbacks of 1 and 1 resulting polyline for sweep would end up with only two points: X: 20.0, Y: 15.0, Z:1.0 and X: 20, Y = 14.85, Z = 1.146. First segment is skipped since it's length is exactly 1, last segment is also skipped but because its length is only 0.5, part of middle segment, starting from end will be skipped as well. Is this expected behavior for you?

pederlh commented 1 year ago

Yes, that is exactly what I would expect. Thank you for working on the fix!