Just checking to see if this is still current :)
thanks,
Mark
Just checking to see if this is still current :)
thanks,
Mark
Afaik, yes.
Happy New Year!
Jeremy
Dear Nate,
Thank you for your challenging query.
It is an interesting question and not easy to solve, as you already mention.
Just as you say, the custom exporter is probably the easiest and most reliable way to go for 3D views.
Another easy and reliable piece of functionality that might help here is specifying the view in a filtered element collector.
Have you made use of that possibility? Can you make use of that?
Here are some discussions by The Building Coder on retrieving visible elements in various situations:
A few more techniques are mentioned in the topic group on retrieving elements using the FilteredElementCollector:
https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.9
Most interesting of all may be the methods implemented by Colin
It determines all views displaying a given set of elements.
He discusses them in more detail here:
I hope this helps.
Please let us know how you get on with this, and especially what solution you end up implementing.
Thank you!
Happy New Year!
Best regards,
Jeremy
Hi je,
Try working through this code: I have added comments at several locations that explains the process. If you still face any doubt please ask again.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; namespace ClassLibrary1 { [Transaction(TransactionMode.Manual)] public class Class1 : IExternalCommand { public Autodesk.Revit.UI.Result Execute(Autodesk.Revit.UI.ExternalCommandData command_data, ref string message, Autodesk.Revit.DB.ElementSet elements) { Document document = command_data.Application.ActiveUIDocument.Document;// replace var with Document (statically-typed) ElementId level_id = new ElementId(1526); // replace var with ElementId, I assume "1526" is the correct level id in your local project ElementId wallTypeId = document.GetDefaultElementTypeId(ElementTypeGroup.WallType);// replace var with Element Id (statically-typed) // // create line on which you will construct a new wall // XYZ point_a = new XYZ(-100, 0, 0); XYZ point_b = new XYZ(100, 0, 0); // for start try making a wall in one plane Curve line = Line.CreateBound(point_a, point_b) as Curve; // Create a bound curve for function to work, a wall cannot be created with unbound line Transaction transaction = new Transaction(document);// no need to to use "Using", Autodesk disposes of all the methods and data in Execute method. { transaction.Start("create walls"); // this command below creates a wall, with default wall type Wall wall = Wall.Create(document, line, level_id, false); // no need of this code, I have commented out this code ( you may remove it). Also the newfamilyinstance method is not used to create a wall.
/*var position = new XYZ(0, 0, 0); var symbolId = document.GetDefaultFamilyTypeId(new ElementId(BuiltInCategory.OST_Walls)); if (symbolId == ElementId.InvalidElementId) { transaction.RollBack(); return Result.Failed; } var symbol = document.GetElement(symbolId) as FamilySymbol; var level = (Level)document.GetElement(wall.LevelId); document.Create.NewFamilyInstance(position, symbol, wall, level, StructuralType.NonStructural); */ transaction.Commit(); } return Result.Succeeded; } } }
If you find that this post solves your query, please mark this as answer.
Thank you
I would recommend, post it on the Revit API forum.
Hi Jeremy, thank you very much for your reply. What I want is a method to create a rebar with an arbitrary 3D shape, which is sometimes required in the longitudinal reinforcement of double-curved bridge. I created a HermiteSpline from a series of XYZ points and use the curve as the center line of rebar. The MultiplanarRebar may not be the solution. However, I found the free form rebar may be able to do that. I will try that.
Thanks
I hope someone can help as I have been working on this for days and the solution continues to evade me.
I am working in Revit 2018 on C# and to avoid complication I have striped my code back to the minimum to try to find the solution.
Ultimately, I am trying to print to PDF utilising PDFCreator whilst providing a series of options to the user through the UI. For the purposes of this however, I have hard code some of the options into my code. One of the options will be the selection of the Settings however for the purposes of this I am utilising “<InSession>”.
My issue is when I SubmitPrint(view) all the options I have pre-set within PrintManager and PrintParameters would appear to disregarded during the print process. For the purpose of my test there is only one view in the ViewSet.
A simple test has been to amend the PageOrientationType and paper sizes, but to no affect.
private void PrintWindowsTestPage() { GetSelectedViews(PDFTreeView.Nodes); ViewSet ViewSetName = selectViewsData.SelectedViews; foreach (Autodesk.Revit.DB.View view in ViewSetName) { PrintManager printManager = m_revitDoc.PrintManager; using (Transaction transaction = new Transaction(m_revitDoc, "Print to PDF")) { transaction.Start(); printManager.PrintSetup.CurrentPrintSetting = printManager.PrintSetup.InSession; printManager.PrintRange=Autodesk.Revit.DB.PrintRange.Select; m_existingExportSetup.PrinterName=PDFPrinterComboBox.SelectedItem as string;//Set to PDFCreator; ViewSheetSetting viewSheetSetting = printManager.ViewSheetSetting; viewSheetSetting.CurrentViewSheetSet.Views=ViewSetName; viewSheetSetting.SaveAs("MyViewSet"); printManager.CombinedFile = true; printManager.PrintToFile=true; PrintSetup pSetup =printManager.PrintSetup; PrintParameters pParam = pSetup.CurrentPrintSetting.PrintParameters; pParam.ZoomType=ZoomType.FitToPage; if (Width>Height) { pParam.PageOrientation=PageOrientationType.Landscape; } else { pParam.PageOrientation=PageOrientationType.Portrait; } pParam.PaperPlacement=PaperPlacementType.Center; foreach (Autodesk.Revit.DB.PaperSize pSize in printManager.PaperSizes) { if (pSize.Name.Equals("A1"))//Work required to get actual Sheet size) { pParam.PaperSize=pSize; break; } } printManager.Apply(); try { pSetup.SaveAs("Test"); } catch (Exception ex) { } printManager.SubmitPrint(view); transaction.RollBack(); } } }
Please can someone help as this is driving me crazy?
In anticipation of your assistance please accept my thanks.
Maybe this free form rebar distribution is exactly what you are after:
Cheers,
Jeremy
Dear darren.hewett,
I also would like to insert a damper exactly like your case. Can you please share the code or give idea how you did please?
Thanks in advance
Ridiculous, a multi-billion dollar software enterprise that cannot make their own API for Revit easy to find.
Hi everyone,
I am trying to create a macro that aligns plans from sheet to sheet.
Now i managed to create a macro that aligns viewports from sheet to sheet, but sometimes annotations on plans will modify the outline of my viewports, making the alignment bogus ( the centers of my viewports align, but it's not what I'm really trying to achieve).
Is there a way, using Revit API, to get the location of the project base point (or other points like grid intersections for example) relative to the viewport outline, so that my plans are aligned from sheet to sheet?
Thanks!
Hi
Thank you for your suggestion. I will look through the sample script you mentioned.
I am trying to create more automation for MEP as possible for my team so it looks very promising :).
Have a nice day.
Best Regards,
Ninh Truong
Hi everyone,
I am trying to find intersection point between riser pipe (vertical) and horizontal pipe (with slope):
using the following code:
Selection selection = uIDocument.Selection; Pipe firstPipe = document.GetElement(selection.PickObject(ObjectType.Element, "Select 1st Pipe")) as Pipe; Pipe riserPipe = document.GetElement(selection.PickObject(ObjectType.Element, "Select riser Pipe")) as Pipe; // Get firstPipe geometry and connectors ConnectorManager connectorManager1 = firstPipe.ConnectorManager; ConnectorSet pipe1connectorset = connectorManager1.Connectors; List<Connector> list1 = new List<Connector>(); foreach (Connector c in pipe1connectorset) { list1.Add(c); } Connector firstpipeconnector1 = list1.First(); Connector firstpipeconnector2 = list1.Last(); Line firstpipeLine = Line.CreateBound(firstpipeconnector1.Origin, firstpipeconnector2.Origin); firstpipeLine.MakeUnbound(); // Get riserpipe geometry and connectors ConnectorManager connectorManager2 = riserPipe.ConnectorManager; ConnectorSet pipe2connectorset = connectorManager2.Connectors; List<Connector> list2 = new List<Connector>(); foreach (Connector c in pipe2connectorset) { list2.Add(c); } Connector riserpipeconnector1 = list1.First(); Connector riserpipeconnector2 = list1.Last(); Line riserpipeLine = Line.CreateBound(riserpipeconnector1.Origin, riserpipeconnector2.Origin); riserpipeLine.MakeUnbound(); // Get intersection point of 2 pipes IntersectionResultArray intersectionResultArray = new IntersectionResultArray(); SetComparisonResult setComparisonResult = firstpipeLine.Intersect(riserpipeLine, out intersectionResultArray); try { XYZ interpoint = intersectionResultArray.get_Item(0).XYZPoint as XYZ; TaskDialog.Show("Info", "The intersection point is " + interpoint.X.ToString()); } catch (Exception) { TaskDialog.Show("Error", "Pipes are not intersected"); }
But the result is :
Although these 2 pipe are actually intersected. So I guess my code have problem with slope pipe of something else.
If you have any experience with this, please help me.
Thank you so much :).
Best Regards,
Cherry Truong
Hi:
Break point at
SetComparisonResult setComparisonResult = firstpipeLine.Intersect(riserpipeLine, out intersectionResultArray);
Step over, and watch the 'setComparisonResult', what is its value? It should be 'Overlap' if two bound lines are truelly intersected. Don't forget to check intersectionResultArray.Size or IsEmpty property to check if two lines are TRUELLY intersected.
Break point at you 'catch' block, check the type and message of the Exception, and modify you catch block like this:
catch (Exception ex) { // Break point here TaskDialog.Show("Error", "Pipes are not intersected"); }
Show furhter infomation of this 'ex' variable. It helps you to diagnose your codes.
And, careful when you use "catch (Exception)", because it swallows any kind of exception.
Hi:
I copied some materials from "Revit 2019 API.chm" help file.
This file is located in the Revit API installation directory, and it's quite useful.
Intersect Method (Curve, IntersectionResultArray)
Namespace: Autodesk.Revit.DB
Assembly: RevitAPI (in RevitAPI.dll) Version: 19.0.0.0 (19.0.0.0)
C# |
---|
publicSetComparisonResultIntersect(Curvecurve,outIntersectionResultArrayresultArray ) |
Hi:
Another suggestion,
You created a Line by obtaining 2 connectors and both end of a Pipe, I cannot tell that it was totally wrong.
But you need to notice that these 2 connectors you obtained from ConnectorManager are End connetors. (Connector.ConnectorType property). If there is a Tap fitting on this Pipe or Duct, there will be problem, because the ConnectorType of a tap connector is Curve. If there is 1 tap connection on a duct, this duct will have 3 connectors at all (2 End, 1 Curve), which means you will never be sure that :
Connector firstpipeconnector1 = list1.First(); Connector firstpipeconnector2 = list1.Last();
returns the corrector End connetor that you want.
Let's talk about your purpose. You want to obtain the Line of a straight MEPCurve element (duct, pipe, cable tray, conduit), is it right?
Simply use the following codes:
(MEPCurve.Location as LocationCurve).Curve as Line
Here is a RevitLookup screenshot for you :)
Thanks for the reply so-chong.
Your solution solved our issue.
with regards;
somu
Glad to hear it works!
Happy New Year!!
Cheers,
So-Chong
Hi
Thank you so much for the great suggestion . I revised my code as following:
Pipe firstPipe = document.GetElement(selection.PickObject(ObjectType.Element, "Select 1st Pipe")) as Pipe; Pipe riserPipe = document.GetElement(selection.PickObject(ObjectType.Element, "Select riser Pipe")) as Pipe; // Get Curve of 2 selected Pipes
LocationCurve locationCurve1 = firstPipe.Location as LocationCurve;
Line firstpipeline = locationCurve1.Curve as Line;
firstpipeline.MakeUnbound();
LocationCurve locationCurve2 = riserPipe.Location as LocationCurve;
Line riserpipeline = locationCurve2.Curve as Line;
riserpipeline.MakeUnbound();
//
// Get intersection point of 2 pipes
IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
SetComparisonResult setComparisonResult = firstpipeline.Intersect(riserpipeline, out intersectionResultArray);
if(setComparisonResult ==SetComparisonResult.Overlap)
{
XYZ interpoint = intersectionResultArray.get_Item(0).XYZPoint as XYZ;
TaskDialog.Show("Info", "The intersection point is " + interpoint.ToString());
}
else
{
TaskDialog.Show("Info", "2 pipes are not intersected");
}
and the result when 2 pipes are intersected is:
When 2 pipes are not intersected:
Once again, thank you for your great help and details explanation.
Have a nice day :).
Best Regards,
Cherry Truong
Dear Dan,
Thank you for your patience and sorry this important question is taking longer than expected to answer.
The same question was also raised in StackOverflow in the thread on how to Initiate BIM360 Docs collaboration programmatically:
https://stackoverflow.com/questions/53892870/initiate-bim360-docs-collaboration-programmatically
We have raised the question with the Revit, C4R, Forge and Desktop Connector development teams, and lively discussion have ensued with no clear answer in sight yet.
We are researching as hard and fast as possible and will provide a more conclusive answer asap.
Best regards,
Jeremy