Hi,
Thanks in advance to anyone with advice or resources on the following.
I'm trying to find a way to convert a hemite spline to a bezier spline.
Take a flexible pipe (or duct) as an example.
I've had limited luck with google, one reference suggested the start and end tangent divided by 3 would give the bezier control points.
It seems Autodesk must have conversion routines in the core as DWG export provides a nurbs curve.
If I measure the control points from the exported curve, it's 451mm from the end point (which I can't seem to relate to a foot unit vector, certainly not by a factor of 3).
Cheers,
Jon
Dear Jon,
Maybe my Google is better than yours 🙂
These look like pretty useful candidates:
Cheers,
Jeremy
Thanks Jeremy for the reply.
Your links are similar to ones I'd found. I've spent some time testing this (setting up a grasshopper script) and confirm that a hermite spline is equivalent to a bezier spline if you divide the hermite tangent vectors by 3 (and add/subtract from the end points).
But I'd like some clarification of the behaviour Revit provides. If I create a flexible pipe (code below), then revit doesn't give me what I specify (by my calculations). I set tangents with vectors 0,0,3 and 3,0,0 and it seems you get vectors that are 0,0,3.1623 and 3.1623,0,0. Why does Revit change this value? Note if I change the code to unit vectors, the pipe shape (and tangent lengths) don't change.
If you query the created pipe (as I'd like to export these objects) using revit lookup, Revit reports normalized tangent vectors (which would be generate a very different spline) on the location curve. How can I accurately extract the hermite tangent vector magnitudes? Should I just assume this constant value that I observed above?
I've attached a spreadsheet calculating the coordinate at a parameter of 0.5 to demonstrate the tangent length discrepency (which matches revit interpolated point at mid parameter).
Cheers,
Jon
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
namespace GGYM
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class ImportIFCGeomGym : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document document = commandData.Application.ActiveUIDocument.Document;
Transaction trn = new Transaction(document, "ggTest");
trn.Start();
FilteredElementCollector collector = new FilteredElementCollector(document).OfClass(typeof(FlexPipeType));
ElementId pipeTypeId = collector.FirstElementId();
// find a pipe system type
FilteredElementCollector sysCollector = new FilteredElementCollector(document);
sysCollector.OfClass(typeof(PipingSystemType));
ElementId pipeSysTypeId = sysCollector.FirstElementId();
Level l = null;
FilteredElementCollector fec = new FilteredElementCollector(document).OfClass(typeof(Level));
foreach(Level lvl in fec)
{
l = lvl;
break;
}
FlexPipe pipe = null;
if (pipeTypeId != ElementId.InvalidElementId && pipeSysTypeId != ElementId.InvalidElementId)
{
List<XYZ> points = new List<XYZ>();
points.Add(new XYZ(0, 0, 0));
points.Add(new XYZ(3, 0, 1));
pipe = FlexPipe.Create(document, pipeSysTypeId, pipeTypeId, l.Id,new XYZ(0,0,3),new XYZ(3,0,0), points);
}
trn.Commit();
return Result.Succeeded;
}
}
}
Hello,
Got a couple of questions:
1) When you use tangents with other magnitudes (say 4 instead of 3) do you see Revit doing floating point changes?
2) What about when you use unit vectors, is it still approximate?
3) I am not familiar with Hermite splines so have to ask, why is the magnitude of the tangent important?
Cheers
Gopinath
Hi Gopinath,
I added 4 lines to the code (pasted below) to set a similar pipe with a tangent of 1 (instead of 3).
1. No noticeable floating point change to the inplane coordinate. Image below.
2. Aproximate to what? I posted the spreadsheet showing the variation in shape. A change in tangent magnitude should significantly affect the shape of the spline.
3. I'm not so familiar with hermite splines either (hence the google references above). It's a curious choice given every other software seems to have opted for nurbs. I'd like to accurately and reliably create and extract geometry with Revit.
I look forward to hearing further expanation about the way Revit provides API access to this geometry.
Cheers,
Jon
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
namespace GGYM
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class ImportIFCGeomGym : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document document = commandData.Application.ActiveUIDocument.Document;
Transaction trn = new Transaction(document, "ggTest");
trn.Start();
FilteredElementCollector collector = new FilteredElementCollector(document).OfClass(typeof(FlexPipeType));
ElementId pipeTypeId = collector.FirstElementId();
// find a pipe system type
FilteredElementCollector sysCollector = new FilteredElementCollector(document);
sysCollector.OfClass(typeof(PipingSystemType));
ElementId pipeSysTypeId = sysCollector.FirstElementId();
Level l = null;
FilteredElementCollector fec = new FilteredElementCollector(document).OfClass(typeof(Level));
foreach(Level lvl in fec)
{
l = lvl;
break;
}
FlexPipe pipe = null;
if (pipeTypeId != ElementId.InvalidElementId && pipeSysTypeId != ElementId.InvalidElementId)
{
List<XYZ> points = new List<XYZ>();
points.Add(new XYZ(0, 0, 0));
points.Add(new XYZ(3, 0, 1));
pipe = FlexPipe.Create(document, pipeSysTypeId, pipeTypeId, l.Id,new XYZ(0,0,1),new XYZ(1,0,0), points);
points.Clear();
points.Add(new XYZ(0, 1, 0));
points.Add(new XYZ(3, 1, 1));
pipe = FlexPipe.Create(document, pipeSysTypeId, pipeTypeId, l.Id,new XYZ(0,0,3),new XYZ(3,0,0), points);
}
trn.Commit();
return Result.Succeeded;
}
}
}
If you still searching a way to do this, check the RevitAPI 2017 they introduced a new method in NurbSpline converting Hermite spline to NurbSpline or Curve.
http://www.revitapidocs.com/2017/cfb90f78-dc27-a305-031d-5e4ffac8a9ce.htm
Wow, cool! Thank you for pointing out! Also