By Aaron Lu

We knew that Rebar has several creation method overloads, CreateFromCurves is one of them,

public static Rebar CreateFromCurves(
Document doc, RebarStyle style, RebarBarType barType,
RebarHookType startHook, RebarHookType endHook, Element host,
XYZ norm, IList<Curve> curves,
RebarHookOrientation startHookOrient,
RebarHookOrientation endHookOrient,
bool useExistingShapeIfPossible, bool createNewShape);

Let's take a look at argument norm and curves,

norm

Type: XYZ

The normal to the plane that the rebar curves lie on.

curves

Type: IList<Curve>

An array of curves that define the shape of the rebar curves. They must belong to the plane defined by the normal and origin. Bends and hooks should not be included in the array of curves.

the RevitAPI.chm shows that the plane of the curves should be perpendicular to the normal.

A customer wants to create 2 rebars, and the plane of curves is truly perpendicular, but the fact is the first Rebar is created successfully, but the second one failed with an InvalidOperationException: Unable to create a RebarShape based on the given curves.

RebarBarType bartype = new FilteredElementCollector(RevitDoc)
.OfClass(typeof(RebarBarType))
.FirstOrDefault(t => t.Name == "8 HPB300") as RebarBarType;
Curve
curve = Line.CreateBound(
new XYZ(5.656152019023, 43.5912980314625, -10.0065608637852),
new XYZ(5.65615201724766, 43.5912980188303, 7.70997373826235));
curves.Add(curve);
curve = Line.CreateBound(
new XYZ(5.65615201724766, 43.5912980188303, 7.70997373826235),
new XYZ(5.65615201724766, 45.2478392340832, 7.70997373826235));
curves.Add(curve);
curve = Line.CreateBound(
new XYZ(5.65615201724766, 45.2478392340832, 7.70997373826235),
new XYZ(5.656152019023, 45.2478392467154, -10.0065608637852));
curves.Add(curve);
// Create succesfully!
Rebar.CreateFromCurves(RevitDoc, RebarStyle.Standard, bartype, null,
null, ele, nml, curves, RebarHookOrientation.Left,
RebarHookOrientation.Left, false, true);
// Problem Curves
List<Curve> curves2 = new List<Curve>();
curve = Line.CreateBound(
new XYZ(6.22700217574493, 43.5110702844365, -10.0065608637852),
new XYZ(6.22700217219427, 43.5110702591722, 7.70997373826235));
curves2.Add(curve);
curve = Line.CreateBound(
new XYZ(6.22700217219427, 43.5110702591722, 7.70997373826235),
new XYZ(6.22700217219427, 45.1676114744251, 7.70997373826235));
curves2.Add(curve);
curve = Line.CreateBound(
new XYZ(6.22700217219427, 45.1676114744251, 7.70997373826235),
new XYZ(6.22700217574493, 45.1676114996894, -10.0065608637852));
curves2.Add(curve);
//InvalidOperationException thrown
// => Unable to create a RebarShape based on the given curves
Rebar.CreateFromCurves(RevitDoc, RebarStyle.Standard, bartype, null,
null, ele, nml, curves2, RebarHookOrientation.Left,
RebarHookOrientation.Left, false, true);

Seems the code is almost the same for the second Rebar creation comparing to the first one except the point positions. But why it throws while the first one doesn't?

I could not find the answer either :-(

My colleague Grzegorz said:

The algorithm of creation of shape is quite complicated. Basically the problem can occur for shapes defined by segments (lines) forming RIGHT ANGLE between themselves. They have to be defined very precisely (different digits on 7 or 8 place after decimal separator can cause exception). The best solution for customer in this situation is to round all coordinates to 6 digits after decimal separator.

So I changed the code like this, then the exception has gone.

curve = Line.CreateBound(
XYZ(6.22700217574493, 43.5110702844365, -10.0065608637852),
XYZ(6.22700217219427, 43.5110702591722, 7.70997373826235));
curves2.Add(curve);
curve = Line.CreateBound(
XYZ(6.22700217219427, 43.5110702591722, 7.70997373826235),
XYZ(6.22700217219427, 45.1676114744251, 7.70997373826235));
curves2.Add(curve);
curve = Line.CreateBound(
XYZ(6.22700217219427, 45.1676114744251, 7.70997373826235),
XYZ(6.22700217574493, 45.1676114996894, -10.0065608637852));
curves2.Add(curve);
....
private XYZ XYZ(double x, double y, double z)
{
return new XYZ(
Math.Round(x, 6), Math.Round(y, 6), Math.Round(z, 6));
}

中文链接