Hi,
I'm looking to explode objects generated as a result of a SAT (or DWG) import into a family document.
I found some code from many years ago suggesting UI automation is the way to achieve this. Is there a better way? (I couldn't find anything).
The code suggested something like this, trouble is the explode button is null. How do you determine the code to detect the explode button (I suspect the button might have subsequently changed).
Thanks,
Jon
Element el = famDoc.GetElement(famDoc.Import(filename, options, view));
if(el != null)
{
UIDocument uiDoc = (new UIApplication(famDoc.Application)).ActiveUIDocument;
SelElementSet seleset = SelElementSet.Create();
SelElementSet selements = uiDoc.Selection.Elements;
seleset.Insert(el);
selements.Clear();
uiDoc.Selection.Elements = seleset;
famDoc.Regenerate();
Process[] processes = Process.GetProcessesByName( "Revit" );
if (processes.Length > 0)
{
PropertyCondition aidCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, "2288");
AutomationElement ae = AutomationElement.FromHandle(processes[0].MainWindowHandle);
AutomationElement explodeButton = ae.FindFirst(TreeScope.Children, aidCondition);
if (explodeButton != null)
{
try
{
InvokePattern invPattern = explodeButton.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
invPattern.Invoke();
}
catch (Exception) { }
}
}
}
Solved! Go to Solution.
Hi,
I'm looking to explode objects generated as a result of a SAT (or DWG) import into a family document.
I found some code from many years ago suggesting UI automation is the way to achieve this. Is there a better way? (I couldn't find anything).
The code suggested something like this, trouble is the explode button is null. How do you determine the code to detect the explode button (I suspect the button might have subsequently changed).
Thanks,
Jon
Element el = famDoc.GetElement(famDoc.Import(filename, options, view));
if(el != null)
{
UIDocument uiDoc = (new UIApplication(famDoc.Application)).ActiveUIDocument;
SelElementSet seleset = SelElementSet.Create();
SelElementSet selements = uiDoc.Selection.Elements;
seleset.Insert(el);
selements.Clear();
uiDoc.Selection.Elements = seleset;
famDoc.Regenerate();
Process[] processes = Process.GetProcessesByName( "Revit" );
if (processes.Length > 0)
{
PropertyCondition aidCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, "2288");
AutomationElement ae = AutomationElement.FromHandle(processes[0].MainWindowHandle);
AutomationElement explodeButton = ae.FindFirst(TreeScope.Children, aidCondition);
if (explodeButton != null)
{
try
{
InvokePattern invPattern = explodeButton.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
invPattern.Invoke();
}
catch (Exception) { }
}
}
}
Solved! Go to Solution.
Solved by Revitalizer. Go to Solution.
Dear GeoGym,
if you want to deal with 3D objects,
instead of exploding an ImportInstance in family context, you could analyze its geometry, extract the solids and create FreeFormElements of them.
FreeFormElement ffe = FreeFormElement.Create(famDoc, solid);
Once created separated Elements, you can do whatever you want with them (add/use face references, parameters, materials).
You can set the offset of single faces.
Maybe that may be more useful and reliable than the UI Automation workaround.
To the code itself:
Since there may be more than one Revit instance opened, you better use System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle
to get the correct window handle.
If you have verified that AutomationId is indeed "2288", it may be a question of correct timing.
Note that re-arranging the ribbon bar may take some time, so you may have to insert a Thread.Sleep().
Also, re-arranging the ribbon bar may result in cached AutomationElements becoming invalid, so you may need to get them again if switching between tabs (Insert tab, Modify tab, ...).
Best regards,
Revitalizer
Dear GeoGym,
if you want to deal with 3D objects,
instead of exploding an ImportInstance in family context, you could analyze its geometry, extract the solids and create FreeFormElements of them.
FreeFormElement ffe = FreeFormElement.Create(famDoc, solid);
Once created separated Elements, you can do whatever you want with them (add/use face references, parameters, materials).
You can set the offset of single faces.
Maybe that may be more useful and reliable than the UI Automation workaround.
To the code itself:
Since there may be more than one Revit instance opened, you better use System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle
to get the correct window handle.
If you have verified that AutomationId is indeed "2288", it may be a question of correct timing.
Note that re-arranging the ribbon bar may take some time, so you may have to insert a Thread.Sleep().
Also, re-arranging the ribbon bar may result in cached AutomationElements becoming invalid, so you may need to get them again if switching between tabs (Insert tab, Modify tab, ...).
Best regards,
Revitalizer
Dear GeomGym and Revitalizer,
Just for your information, I recently raised a wish list item for this functionality, CF-2130 [API wish: access to explode command].
Arnošt keeps saying we should raise wish list items for Revit API functionality instead of hacking ... let's see who gets this one solved first 🙂
Cheers,
Jeremy
Dear GeomGym and Revitalizer,
Just for your information, I recently raised a wish list item for this functionality, CF-2130 [API wish: access to explode command].
Arnošt keeps saying we should raise wish list items for Revit API functionality instead of hacking ... let's see who gets this one solved first 🙂
Cheers,
Jeremy
Hi Jeremy,
I think there are many wishes which will never be satisfied.
So wait for version 2019 to get access to explode command ?
😉
So there is no alternative to finding workarounds.
Cheers,
Revitalizer
Hi Jeremy,
I think there are many wishes which will never be satisfied.
So wait for version 2019 to get access to explode command ?
😉
So there is no alternative to finding workarounds.
Cheers,
Revitalizer
Hi Revitalizer and Jeremy,
Thanks for the suggestion about extracting the solid, much cleaner and better and works well.
Jeremy, it's always welcome to see improvements to the API. I agree that raising requests is a great thing to do.
Thanks,
Jon
Hi Revitalizer and Jeremy,
Thanks for the suggestion about extracting the solid, much cleaner and better and works well.
Jeremy, it's always welcome to see improvements to the API. I agree that raising requests is a great thing to do.
Thanks,
Jon
Any luck with exploding an imported cad element.
In Revit 2015 I'm being forced down the automation line. But I can't seem to get to the Ribbon? The below code fails at ribbonWnd.
Any help appreciated.
Regards
David
Dim processes As Process() = Process.GetProcessesByName("Revit") Dim mainWndFromHandle As AutomationElement = AutomationElement.FromHandle(processes(0).MainWindowHandle) Dim nameRibbonCondition As New PropertyCondition(AutomationElement.NameProperty, "RibbonHostWindow") Dim typeRibbonCondition As New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane) Dim andCondition As New AndCondition(typeRibbonCondition, nameRibbonCondition) Dim ribbonWnd As AutomationElement = mainWndFromHandle.FindFirst(TreeScope.Children, andCondition)
Any luck with exploding an imported cad element.
In Revit 2015 I'm being forced down the automation line. But I can't seem to get to the Ribbon? The below code fails at ribbonWnd.
Any help appreciated.
Regards
David
Dim processes As Process() = Process.GetProcessesByName("Revit") Dim mainWndFromHandle As AutomationElement = AutomationElement.FromHandle(processes(0).MainWindowHandle) Dim nameRibbonCondition As New PropertyCondition(AutomationElement.NameProperty, "RibbonHostWindow") Dim typeRibbonCondition As New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane) Dim andCondition As New AndCondition(typeRibbonCondition, nameRibbonCondition) Dim ribbonWnd As AutomationElement = mainWndFromHandle.FindFirst(TreeScope.Children, andCondition)
+1
+1
This is an interesting idea, but can you elaborate how would you extract the solids from imported SAT file and iterate through them?
SAT file comes in as one element, so not how to filter for solids.
Thanks
This is an interesting idea, but can you elaborate how would you extract the solids from imported SAT file and iterate through them?
SAT file comes in as one element, so not how to filter for solids.
Thanks
Hi,
To get the solid(s) of your ImportInstance, you could have a closer look at these code samples:
https://forums.autodesk.com/t5/revit-api-forum/getting-beam-column-and-wall-geometry/m-p/8138893
Revitalizer
Hi,
To get the solid(s) of your ImportInstance, you could have a closer look at these code samples:
https://forums.autodesk.com/t5/revit-api-forum/getting-beam-column-and-wall-geometry/m-p/8138893
Revitalizer
I am afraid that your +1 here in the forum will go unnoticed.
If you ensure that a wish list entry is present for this in the Revit Idea Station and add your votes for that, they will have real impact.
Cheers,
Jeremy
I am afraid that your +1 here in the forum will go unnoticed.
If you ensure that a wish list entry is present for this in the Revit Idea Station and add your votes for that, they will have real impact.
Cheers,
Jeremy
Thank you @Revitalizer
As the tutorial suggests, I was able to use the get_geometry() method to iterate through the geometries in imported element and look for solids. Then I'm using FreeFormElement.Create(doc, solid) to recreate the solid(s).
I tested this on an SAT file I made in Rhino, the file has one cube and one cylinder. Once imported into Revit and going through the workflow above, the result is both cube and cylinder in one single FreeFormElement. (see screenshot attached)
I was expecting two separate elements. Am I missing something? or is it SAT property that doesn't break down to primitive geometry?
Thanks,
-Morteza
Thank you @Revitalizer
As the tutorial suggests, I was able to use the get_geometry() method to iterate through the geometries in imported element and look for solids. Then I'm using FreeFormElement.Create(doc, solid) to recreate the solid(s).
I tested this on an SAT file I made in Rhino, the file has one cube and one cylinder. Once imported into Revit and going through the workflow above, the result is both cube and cylinder in one single FreeFormElement. (see screenshot attached)
I was expecting two separate elements. Am I missing something? or is it SAT property that doesn't break down to primitive geometry?
Thanks,
-Morteza
Hi,
you could use SolidUtils.SplitVolumes(yourFusionedSolid) to split it into separate Solids.
A Solid obviously can be made of unconnected parts.
Revitalizer
Hi,
you could use SolidUtils.SplitVolumes(yourFusionedSolid) to split it into separate Solids.
A Solid obviously can be made of unconnected parts.
Revitalizer
Thank you!
that did the trick
Thank you!
that did the trick
Any idea why the recreated elements (using FreeformElement.Create ) still show as "imported categories" in visibility graphics? Is there a way to avoid that?
Thanks
Any idea why the recreated elements (using FreeformElement.Create ) still show as "imported categories" in visibility graphics? Is there a way to avoid that?
Thanks
Hi,
you need to set yourFreeFormElement.SubCategory.
You can add a new Category to your Family's FamilyCategory.SubCategories and assign this sub-Category to your FFE.
Revitalizer
Hi,
you need to set yourFreeFormElement.SubCategory.
You can add a new Category to your Family's FamilyCategory.SubCategories and assign this sub-Category to your FFE.
Revitalizer
I am doing that by using the code below:
public void AssignSubCategory(Document document, FreeFormElement element, String subCategoryName, String materialName) { Category cat = document.OwnerFamily.FamilyCategory; Category subCat = document.Settings.Categories.NewSubcategory(cat, subCategoryName); ElementId materialId = Material.Create(document, materialName); subCat.Material = document.GetElement(materialId) as Material; element.Subcategory = subCat; }
foreach (Solid solid in solids) { FreeFormElement nativeSolid = FreeFormElement.Create(doc, solid); AssignSubCategory(doc, nativeSolid, "subCategory "+ct.ToString(), "material "+ct.ToString()); ct += 1; }
The result model has the subcategories assigned correctly but for some reason also shows as "Imports in Families" in visibility graphics. (see screenshots attached).
Is there anyway to remove it from the "imports in Families"?
I am doing that by using the code below:
public void AssignSubCategory(Document document, FreeFormElement element, String subCategoryName, String materialName) { Category cat = document.OwnerFamily.FamilyCategory; Category subCat = document.Settings.Categories.NewSubcategory(cat, subCategoryName); ElementId materialId = Material.Create(document, materialName); subCat.Material = document.GetElement(materialId) as Material; element.Subcategory = subCat; }
foreach (Solid solid in solids) { FreeFormElement nativeSolid = FreeFormElement.Create(doc, solid); AssignSubCategory(doc, nativeSolid, "subCategory "+ct.ToString(), "material "+ct.ToString()); ct += 1; }
The result model has the subcategories assigned correctly but for some reason also shows as "Imports in Families" in visibility graphics. (see screenshots attached).
Is there anyway to remove it from the "imports in Families"?
Hi,
I need a method to explode CAD files once imported I think the profs are using a cad script first then bringing the aftermath into revit and operating on the 1k+ lines you get from aussie manufacturers in the worst of cases.
did you start an idea station or wishlist for this or at least do you know of one?
Hi,
I need a method to explode CAD files once imported I think the profs are using a cad script first then bringing the aftermath into revit and operating on the 1k+ lines you get from aussie manufacturers in the worst of cases.
did you start an idea station or wishlist for this or at least do you know of one?
Why do the solutions described above not work in your case? How do they fail? What exactly are you trying to achieve?
Why do the solutions described above not work in your case? How do they fail? What exactly are you trying to achieve?
Can't find what you're looking for? Ask the community or share your knowledge.