How to draw ModelNurbSpline

How to draw ModelNurbSpline

Anonymous
Not applicable
2,752 Views
6 Replies
Message 1 of 7

How to draw ModelNurbSpline

Anonymous
Not applicable

 

I actually want to draw HermiteSpline.

 

After reading here, (from my understanding) we cant draw HermiteSpline, but we can draw NurbsSpline.

https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/Revit-API/files/GUID-...

 

Then i found that we can create NurbSpline from HermiteSpline like this, but i am not sure how is the result.

NurbSpline nurbspline = NurbSpline.Create(hermitespline);

 

Then i try to draw NurbSpline using below method:

ModelNurbSpline modelnurbspline = doc.Create.NewModelCurve(nurbspline, sketchplane) as ModelNurbSpline;

 

Then i've got this message:

An exception of type 'Autodesk.Revit.Exceptions.ArgumentException' occurred in RevitAPI.dll but was not handled in user code
Additional information: Curve must be in the plane
Parameter name: pCurveCopy occurred

 

Question is, how to create SketchPlane for NurbsSpline to create ModelNurbSpline? or is there any other workaround?

 

Also, how to use SetSketchPlaneAndCurve method?

0 Likes
Accepted solutions (1)
2,753 Views
6 Replies
Replies (6)
Message 2 of 7

FAIR59
Advisor
Advisor

you can query a point on the spline for the normal of the plane of the curve using curve.ComputeDerivatives()

 

List<XYZ> points = new List<XYZ>()
  { new XYZ(0,2,3), new XYZ(-4,0,4) , new XYZ(5,-3,4)};
List<double> weights = new List<double>() { 1,1,1 };
NurbSpline spline = NurbSpline.CreateCurve(points,weights) as NurbSpline;
XYZ origin = spline.GetEndPoint(0);
XYZ normal = spline.ComputeDerivatives(0, true).BasisZ.Normalize();
using (Transaction t = new Transaction(doc, "create spline"))
	{
		t.Start();
		SketchPlane skPlane = SketchPlane.Create(doc,Plane.CreateByNormalAndOrigin(normal,origin));
		ModelCurve cv = doc.Create.NewModelCurve(spline,skPlane);
		t.Commit();
	}
Message 3 of 7

Anonymous
Not applicable

Here is my code. i got same error: Curve must be in the plane

 

Curve curv = edge.AsCurve();
if (curv is HermiteSpline) {
HermiteSpline hermitespline = curv as HermiteSpline;
NurbSpline nurbspline = NurbSpline.Create(hermitespline);
XYZ origin = nurbspline.GetEndPoint(0);
XYZ normal = nurbspline.ComputeDerivatives(0, true).BasisZ.Normalize();
SketchPlane skPlane = SketchPlane.Create(doc, Plane.CreateByNormalAndOrigin(normal, origin));
ModelCurve cv = doc.Create.NewModelCurve(nurbspline, skPlane);
}

 

 

Anyway thanks. The closest model curve i can draw is an arc using part of your code:

 

Curve curv = edge.AsCurve();
if (curv is HermiteSpline) {
Arc arc = Arc.Create(curv.GetEndPoint(0), curv.GetEndPoint(1), curv.Evaluate(0.5, true));
XYZ origin = arc.GetEndPoint(0);
XYZ normal = arc.ComputeDerivatives(0, true).BasisZ.Normalize();
SketchPlane skPlane = SketchPlane.Create(doc, Plane.CreateByNormalAndOrigin(normal, origin));
ModelCurve cv = doc.Create.NewModelCurve(arc, skPlane);

}

 

RampToFloor.png

0 Likes
Message 4 of 7

FAIR59
Advisor
Advisor
Accepted solution

The nurbspline from a hermitespline is apparently not in a plane.

You project the controlpoints on a plane and "recreate the nurbspline.

 

 				NurbSpline spline = NurbSpline.CreateCurve(pickedCurve) as NurbSpline;
 				StringBuilder sb = new StringBuilder();
				XYZ origin = spline.GetEndPoint(0);
				XYZ point1 = spline.GetEndPoint(1);
				XYZ direction = point1.Subtract(origin).Normalize();
				double distance =0;
				XYZ Ydir = direction.IsAlmostEqualTo(XYZ.BasisZ)? XYZ.BasisX: XYZ.BasisZ;
				XYZ normal = direction.CrossProduct(Ydir).CrossProduct(direction);
				using (TransactionGroup tg = new TransactionGroup(doc,"create NurbSpline"))
				{
					tg.Start();
					SketchPlane skPlane = null;
					using (Transaction t = new Transaction(doc, "create spline"))
					{
						t.Start();
						skPlane = SketchPlane.Create(doc,Plane.CreateByNormalAndOrigin(normal,origin));
						t.Commit();
					}
					normal =skPlane.GetPlane().Normal;
					IList<XYZ> newCntrlPoints = new List<XYZ>();
					foreach (XYZ point in spline.CtrlPoints)
					{
						distance  = normal.DotProduct(point.Subtract(origin));
						newCntrlPoints.Add(point.Subtract(normal.Multiply(distance)));
						sb.AppendLine(string.Format("{0:f8}  {1}",distance,point));
					}
					spline.SetControlPointsAndWeights(newCntrlPoints,spline.Weights);
					using (Transaction t = new Transaction(doc, "create spline"))
					{
						t.Start();
						ModelCurve cv = doc.Create.NewModelCurve(spline,skPlane);
						t.Commit();
					}
					tg.Commit();
				}
				TaskDialog.Show("debug", sb.ToString());
Message 5 of 7

FAIR59
Advisor
Advisor

one further thought: 3 control points of a nurbspline should be in the "official" plane, as long as the 3 points aren't on the same line.

 

for Revit 2017/2018 you can create that plane using:    Plane.CreateByThreePoints().

 

0 Likes
Message 6 of 7

Anonymous
Not applicable

Hi Fair59,

 

Thanks a lot.. able to draw NurbSpline.

But.. in this my ramp case, the result is the same like the drawing in my previous post.

where i convert the HermiteSplite to Arc.

 

I just realised ModelHermiteSpline Class exist, but how to use?

Smiley Frustrated
RampToFloor2.png

0 Likes
Message 7 of 7

Anonymous
Not applicable

the code is too complicated for me to understand.

so do the statement of "3 control points of a nurbspline should be in the "official" plane"

 

i am in the learning process anyway.. thanks again.. FAIR59

0 Likes