Until now, The Building Coder included no example at all of using the NewBlend method. A developer ran into an issue using it, and my colleague Joe Ye created an external command to resolve the issue, so I took and added it. Here is the issue that prompted this:
Question: I am trying to create a blend with two circular profiles, but it is not working. Can you please provide some solution for us?
Answer: After several tests, I found that the issue is due to the fact that the top and bottom profiles should contain at least two curves.
I split the circle that you were using for you profile into two semi-circle arcs. Now the command successfully creates the new blend.
I used Joe's sample code to create a new Building Coder sample external command CmdNewBlend. It exercises the following helper method CreateBlend for the actual new blend creation:
static Blend CreateBlend( Document doc ) { Debug.Assert( doc.IsFamilyDocument, "this method will only work in a family document" ); Application app = doc.Application; Autodesk.Revit.Creation.Application creApp = app.Create; Autodesk.Revit.Creation.FamilyItemFactory factory = doc.FamilyCreate; double startAngle = 0; double midAngle = Math.PI; double endAngle = 2 * Math.PI; XYZ xAxis = XYZ.BasisX; XYZ yAxis = XYZ.BasisY; XYZ center = XYZ.Zero; XYZ normal = -XYZ.BasisZ; double radius = 0.7579; Arc arc1 = creApp.NewArc( center, radius, startAngle, midAngle, xAxis, yAxis ); Arc arc2 = creApp.NewArc( center, radius, midAngle, endAngle, xAxis, yAxis ); CurveArray baseProfile = new CurveArray(); baseProfile.Append( arc1 ); baseProfile.Append( arc2 ); XYZ center2 = new XYZ( 0, 0, 1.27 ); Arc arc3 = creApp.NewArc( center2, radius, startAngle, midAngle, xAxis, yAxis ); Arc arc4 = creApp.NewArc( center2, radius, midAngle, endAngle, xAxis, yAxis ); CurveArray topProfile = new CurveArray(); topProfile.Append( arc3 ); topProfile.Append( arc4 ); Plane basePlane = creApp.NewPlane( normal, center ); SketchPlane sketch = factory.NewSketchPlane( basePlane ); Blend blend = factory.NewBlend( true, topProfile, baseProfile, sketch ); return blend; }
The command mainline simply checks that the current document is indeed a family document and then calls CreateBlend:
[Transaction( TransactionMode.Automatic )] [Regeneration( RegenerationOption.Manual )] class CmdNewBlend : IExternalCommand { public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; if( doc.IsFamilyDocument ) { Blend blend = CreateBlend( doc ); return Result.Succeeded; } else { message = "Please run this command " + "in a family document."; return Result.Failed; } } }
This is what the resulting blend looks like in the family editor:
I modified the code to create a more interesting shape using a skewed rectangle for the top profile like this:
CurveArray topProfile = new CurveArray(); bool circular_top = false; if( circular_top ) { // create a circular top profile: XYZ center2 = new XYZ( 0, 0, 1.27 ); Arc arc3 = creApp.NewArc( center2, radius, startAngle, midAngle, xAxis, yAxis ); Arc arc4 = creApp.NewArc( center2, radius, midAngle, endAngle, xAxis, yAxis ); topProfile.Append( arc3 ); topProfile.Append( arc4 ); } else { // create a skewed rectangle top profile: XYZ[] pts = new XYZ[] { new XYZ(0,0,3), new XYZ(2,0,3), new XYZ(3,2,3), new XYZ(0,4,3) }; for( int i = 0; i < 4; ++i ) { topProfile.Append( creApp.NewLineBound( pts[0 == i ? 3 : i - 1], pts[i] ) ); } }
Running that in a new family document based on the Metric Column template creates a shape like this:
Here is what it looks like in plan view:
Here is version 2011.0.78.0 of The Building Coder samples including the complete source code and Visual Studio solution with the new command.
Jeremy,
I'm currently in the process of importing a lot of geometric solid primitives into Revit Families (RAC 2012). Each of the primitives is build of 8 points: 4 coplanar points that make the closed top profile, and 4 coplanar points for the bottom profile. Top and bottom profile planes are NOT necessarily parallel.
I've based my code on the CreateBlend method in the example above and on a similar method that comes with the RAC 2012 SDK (FamilyCreation\GenericModelCreation).
The code works fine as long as top and bottom profiles are perfectly horizontal (all Z-coordinates for top-profile points equal, all Z-coordinates for bottom-profile points equal). But, as soon as there is an inclination in top or bottom profile planes, factory.NewBlend(...) generates an "internal error: code1" exception and the blend is not created. This means that about 40% of my data gets rejected. Question: is there another, less critical, function than NewBlend()to handle this kind of geometry, or do I have an error in my code (which works fine for the other 60% of the data).
Here is the important part of my code, nothing special to it, I think. The sketchPlane's normal is XYZ.BasisZ, it's origin is XYZ.Zero.
Thank you, any help will be greatly appreciated (I've been struggling for 3 day's now...)
Luc
// Create top and base profiles
CurveArray topProfile = new CurveArray();
CurveArray bottomProfile = new CurveArray();
// create one blend
Line line01 = revitApp.Create.NewLineBound(nCoords[0], nCoords[1]);
Line line02 = revitApp.Create.NewLineBound(nCoords[1], nCoords[3]);
Line line03 = revitApp.Create.NewLineBound(nCoords[3], nCoords[2]);
Line line04 = revitApp.Create.NewLineBound(nCoords[2], nCoords[0]);
bottomProfile.Append(line01);
bottomProfile.Append(line02);
bottomProfile.Append(line03);
bottomProfile.Append(line04);
Line line11 = revitApp.Create.NewLineBound(nCoords[4], nCoords[5]);
Line line12 = revitApp.Create.NewLineBound(nCoords[5], nCoords[7]);
Line line13 = revitApp.Create.NewLineBound(nCoords[7], nCoords[6]);
Line line14 = revitApp.Create.NewLineBound(nCoords[6], nCoords[4]);
topProfile.Append(line11);
topProfile.Append(line12);
topProfile.Append(line13);
topProfile.Append(line14);
// here create one blend
Blend blend = creationFamily.NewBlend(true, topProfile, bottomProfile, sketchPlane);
Posted by: Luc Van Asch | March 09, 2012 at 09:40
Dear Luc,
Oh dear, sorry to hear you have been struggling so. Have you solved it in the meantime? I hope so. What was the issue and the solution? If not, have you seen the following suggestion to create intermediate model lines from you input data and then test using those through the user interface to manually create the desired shape, in the hope that any occurring errors will be reported in more informative detail there?
http://thebuildingcoder.typepad.com/blog/2009/07/debug-geometric-form-creation.html
Cheers, Jeremy.
Posted by: Jeremy Tammik | June 03, 2012 at 14:59
Hi Jeremy,
I’m using the Revit 2012 API.
I want to create a blend with 8 curves in the BottomProfile and 4 curves in the TopProfile.
When I try to this the Document.FamilyCreate.NewBlend method gives an ApplicationException: "Unexpected internal error: code 1."
" at Autodesk.Revit.Creation.FamilyItemFactory.NewBlend(Boolean isSolid, CurveArray topProfile, CurveArray baseProfile, SketchPlane sketchPlane)”
How can I create such a blend?
Posted by: Arjen de Pater | September 11, 2012 at 05:15
Dear Arjen,
You should definitely first of all ensure that you can create the same shape through the user interface, as recommended here:
http://thebuildingcoder.typepad.com/blog/2009/07/debug-geometric-form-creation.html
If that fails, then it will fail through the API as well.
It may also provide you with a more informative error message.
Cheers, Jeremy.
Posted by: Jeremy Tammik | September 11, 2012 at 09:41
Dear Jeremy,
Yes, I can create the blend in the UI.
The problem is the different number of curves in the BottomProfile and TopProfile because the NewBlend method lacks a parameter for the VertexConnectionMap.
Thanks,
Arjen
Posted by: Arjen de Pater | September 12, 2012 at 09:43
Dear Arjen,
I see that you raised the same issue in the ADN DevHelp Online case 07615940 [I want to create a blend with 8 curves in the BottomProfile and 4 curves in the TopProfile].
It helps us work more efficiently if you let us know that you are inquiring simultaneously through multiple channels.
Have you looked at the following NewSweptBlend samples, in case they provide any useful hints?
http://thebuildingcoder.typepad.com/blog/2010/03/newsweptblend.html
http://adndevblog.typepad.com/aec/2012/08/newsweptblend-code-sample.html
If they do not help, I would suggest submitting a detailed script of how you succeed in the form creation through the user interface, plus a complete read-to-compile Visual Studio solution implementing the same thing through the API, demonstrating how it fails, and if needed a minimal sample Revit model to run it in... through the ADN DevHelp online case is probably the simplest way.
Cheers, Jeremy.
Posted by: Jeremy Tammik | September 12, 2012 at 11:20
Dear Arjen,
Here is another new post that ought to answer your question in full:
http://adndevblog.typepad.com/aec/2012/09/blending-two-profiles-with-different-topbottom-vertex-counts-.html
Cheers, Jeremy.
Posted by: Jeremy Tammik | September 12, 2012 at 14:02