How to Move and Disjoin using API

How to Move and Disjoin using API

Anonymous
Not applicable
3,165 Views
10 Replies
Message 1 of 11

How to Move and Disjoin using API

Anonymous
Not applicable

Hi,

 

I have an add-in that uses ElementTransformUtils.MoveElement quite often. Recently I've encountered certain elements that i'm unable to move do to work plane restrictions.

 

Is there a way to emulate the user selecting "Disjoin" in UI when moving elements using the API?

 

For example, I have instance of a Face Based Generic Model family who's current work plane is "<not associated>". Using the Revit UI, I can move the object in any direction if I select "Disjoin". If I do not select "Disjoin" then the move is restricted to the direction of the original work plane family was associated with but no longer exists. This same restrcition exists when moving the object using API, and I'm unable to find a way to emulate selecting "Disjoin" during the API call.

 

Thanks in advance for any help.

 

Jon

0 Likes
Accepted solutions (1)
3,166 Views
10 Replies
Replies (10)
Message 2 of 11

jeremytammik
Autodesk
Autodesk

Try to follow the standard approach for researching how to solve a Revit API programming task:

 

https://thebuildingcoder.typepad.com/blog/2017/01/virtues-of-reproduction-research-mep-settings-onto...

 

Specifically, analyse in depth precisely what changes are generated in the Revit database by manually performing the disjoin action.

 

Once you have nailed that down, you may be able to easily reproduce the same modification programmatically through the API.

 

Please let us know how you fare, and the best of luck to you!

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 3 of 11

Anonymous
Not applicable

Thanks Jeremy,

 

I took your advice and analyzed what happens when using disjoin during manual move. What I found is interesting but leads me to believe accomplishing similar via API is not possible, unless of course I’m missing something, so I could use some help please.

 

Below is what I discovered; I will do my best to explain steps taken and result (bear with me…). Also created a video if you prefer to just watch… https://youtu.be/QceKgq7jBw4

 

  1. I started a blank project and added a reference plane. This first screenshot illustrates that NO sketch plane is created by simply adding a reference plane.

jalbert7BW3D_0-1590078166295.png

 

 

  1. Next, I placed a face-based family selecting the reference plane as host. Shown in image below you can see the reference plane is listed as the family instances host.

jalbert7BW3D_1-1590078166305.png

 

 

  1. Next, looking back in the DB we notice a new Sketch Plane has been created as result of placing the family instance on reference plane.
    1. Note: Exploring the API, I cannot find a relationship between the newly created sketch plane and the reference plane or family instance, but there certainly must be one somehow.

jalbert7BW3D_2-1590078166312.png

 

 

  1. Next, I deleted the reference plane to simulate our situation of interest, a face-based family instance with work plane of “not associated”. We can see in image below the “host” of family instance is now “null”.
    1. Note: Although the host shows null, I believe the “host” is the sketch plane that was created when initially placing the family.

jalbert7BW3D_3-1590078166317.png

 

 

  1. Next, I manually moved the family instance and selected “disjoin”. As seen in image below, the result of moving with disjoin is that a new sketch plane was created which is apparently the new “host” for our family instance.
    1. Note: The original sketch plane remains but is essentially a junk object in our DB now as it is not being used by anything. If I were to perform this type of move 10 more times, I would end up with many junk sketch planes in my DB.

jalbert7BW3D_4-1590078166323.png

 

  1. Now, using the API, if I try to move the family instance using ElementTransformUtils.MoveElement, it will only move in a direction that remains in line with the “host” sketch plane.
    1. Note: I did find that if I were able to determine the sketch plane element via API that I would be able to move the family instance and the sketch plane essentially eliminating need to “disjoin” the two. However as stated above I cannot find a way to determine this relationship via API. This can be manually demonstrated by selecting the sketch plane by ID, then also selecting the family instance, and manually moving. Doing so allows user to move family instance without selecting disjoin.

 

To conclude, my main problem is that I cannot use the API to determine the associated sketch plane of a “not associated” face-based family instance. If I could determine the sketch plane then problem solved.

0 Likes
Message 4 of 11

Anonymous
Not applicable

@jeremytammik  any thoughts on my findings?

 

Based on what I found I feel maybe the Revit API could use an enhancement in determining sketch plane for "not associated" face based family instances.

 

Thanks,

 

Jon

0 Likes
Message 5 of 11

FAIR59
Advisor
Advisor
Accepted solution

You can find the inverse relation. Given a sketchplane, you can find if the element "belongs" to that plane. If you delete a sketchplane, then elements that use the sketchplane will also be deleted. So loop through all the sketch planes and see if the element gets deleted when deleting the sketchplane (temporary).

string sketchplane_Name = elem.get_Parameter(BuiltInParameter.SKETCH_PLANE_PARAM).AsString();
int index = sketchplane_Name.IndexOf(':');
if(index>=0) sketchplane_Name = sketchplane_Name.Remove(0,index+2);
			
IEnumerable<ElementId> sketchplanes = new FilteredElementCollector(doc)
				.OfClass(typeof(SketchPlane))
				.ToElementIds();
List<ElementId> deleted = new List<ElementId>();
SketchPlane plane = null;
using (Transaction t = new Transaction(doc,"dummy"))
{
	t.Start();
	foreach(ElementId id in sketchplanes)
	{
		Element sk = doc.GetElement(id);
		if(!sk.Name.Contains(sketchplane_Name)) continue;
		using (SubTransaction st = new SubTransaction(doc))
		{
			st.Start();
			deleted = doc.Delete(sk.Id).ToList();
			st.RollBack();
		}
		if(deleted.Contains(elem.Id))
		{
			plane = sk as SketchPlane;
			break;
		}
	}
	t.RollBack();
}
Message 6 of 11

Anonymous
Not applicable

Thanks @FAIR59 , I'll keep this in mind as a worst case work around, but I'm afraid this will cause lengthy processing time for my task which I cannot afford.

 

Thanks for the creative approach though, I can see how this would work.

 

Hopefully we can get a proper solution in the API.

 

 

0 Likes
Message 7 of 11

jeremytammik
Autodesk
Autodesk

Dear Jon,

 

Thank you very much for your detailed description and helpful video, and thanks to Fair59 for his very helpful suggestion.

 

You should benchmark the suggestion before discarding it as 'lengthy processing time for my task which I cannot afford'. That may not be the case at all!

 

Anyway, your video is really very cool and helpful to explain a tricky situation and hint at several possible solutions.

 

Here are my notes from the video, for thinking purposes:

 

  • new project
  • several sketch planes exist, all associated with level 1
  • add reference plane to project --> no new sketch plane created yet
  • load a face based family
  • place an instance of it on the ref plane --> new sketch plane is created
  • instance host is ref plane
  • delete ref plane
  • host is null
  • work plane is now 'not associated'
  • sketch plane still exists, now renamed to 'not associated'
  • moving family instance is still restricted to the sketch plane
  • disjoin allows moving it off the sketch plane and a new sketch plane is created

 

Possible solutions you suggest:

 

  • disjoin -- is it accessible via api?
  • move is also possible if the sketch plane and the instance are both selected and moved simultaneously

 

For that, you wish to access the sketch plane via API.

 

I believe there is a wish list item for that functionality in the Revit Idea Station. Please search and vote for it!

 

Even without that API, here is an approach that may possibly be more direct than the one suggested by Fair59:

 

Use an undocumented ElementId relationship, if there is one:

 

https://thebuildingcoder.typepad.com/blog/2011/11/undocumented-elementid-relationships.html

 

The mysterious sketch plane was created by placing the instance on the ref plane.

 

Quite possibly, the sketch plane element id is the same as the family instance element id, plus or minus one or two or so.

 

If that is true and reliable in all the situations you encounter, then you could easily select the proper sketch plane for any family instance that you need to move.

 

That would enable you to move the sketch plane and the instance simultaneously, as per your second suggestion in the video.

 

I hope this helps.

 

Best regards and good luck!

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 8 of 11

Anonymous
Not applicable

Thanks Jeremy,

 

I will try out the workaround solution provided by @FAIR59 and respond back to this post for results. At this point it does seem like my only solution. I will mark it as solution for this post.

 

I could find relevant post in Ideas Station so I created my own. IF anyone comes across this post and wishes for the same feature in API please vote for it here...

https://forums.autodesk.com/t5/revit-ideas/api-method-to-get-sketchplane-of-not-associated-face-base...

 

I did a little research regarding element id's like you mention but doesn't appear to be any logic there, especially since 2 separate family instances can refer to the same sketch plane.

 

Regarding disjoin, based on my research I do not see any way to achieve this type of move via API.

 

Thanks,

 

Jon

 

 

0 Likes
Message 9 of 11

jeremytammik
Autodesk
Autodesk

Dear Jon,

 

Thank you for your new wish list entry.

 

The one I was thinking of is more generic:

 

  

You might want to vote for that as well.

 

One thing that neither you nor Fair59 mention is checking the sketch plane geometry and trying to identify it that way, or maybe even modify its location via its API.

 

From the family instance, can you find a way to determine the origin and normal vector of the work plane that it has been placed on?

 

If yes, then you could search all the sketch planes in the database for a matching plane orientation.

 

Plane equality is determined by four real numbers: X, Y, Z of its normal vector and signed distance from the origin.

 

If you can use that to pair up the family instance with the sketch plane 'hosting' it, you would have the relationship you seek.

 

Furthermore, if you can modify the sketch plane normal vector and origin to move it where you want, the family instance might follow it to the desired location.

 

Otherwise, I am sure that Fair59's solution will also do the job.

 

I look forward to hearing how it works out and what the performance looks like.

 

Thank you!

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 10 of 11

Anonymous
Not applicable

Thanks Jeremy,

 

I'll take your additional thoughts into consideration. May be a couple weeks before I'm able to test this out and report back.

 

Jon

0 Likes
Message 11 of 11

lionel.kai
Advisor
Advisor

Reading the above, I was wondering if moving the sketch plane WITH the element is actually even a viable solution, as I would think that other (undesired) elements would also potentially get moved?

 

Just curious. I don't have a specific task related to this behavior - I found this post while researching Disjoin in the API.


Lionel J. Camara
BIM Manager at KAI Hawaii, Inc. - Structural and Forensic Engineers
Autodesk Certified Professional
0 Likes