Transaction with Loops

Hi,

I’m trying to move an element towards another element in iterative steps, where i have my element .MoveByVector(scaled_vector)

I want my element to keep moving and stops until it meets a condition where the intersection volume of both solids == volume of the second element.

So far I’ve come up with this code:

import sys

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *


import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
TransactionManager.Instance.ForceCloseTransaction()


# instantiate current document
docs = DocumentManager.Instance.CurrentDBDocument

#INPUT
element1 = IN[0]
element2 = IN[1]
vector = IN[2]

#Solids
solid_element1 = element1.Solids
solid_element2 = element2.Solids
intersection = solid_element1[0].IntersectAll(solid_element2)
volume_intersection = intersection[0].Volume
volume_element2 = solid_element2[0].Volume

#Vector
scaled_vector = vector.Scale(0.1)

#ACTION 
with Transaction(docs, "move family transaction") as transaction:
    transaction.Start()
    while True:
        moved_element = element1.MoveByVector(scaled_vector)
        if volume_intersection == volume_element2:
            break
        elif volume_intersection == 0:
            break
    transaction.Commit() 

    
OUT = moved_element

However it’s returning the following:

Is there a specific way to use transaction with loops or having multiple transactions at once?

So Inhave an example of repeating a transaction until a condition is met which I’ll link to… however it’s a bad idea in most cases for a few reasons.

  1. You could do the action once, 100 times, or infinitely (say the initial mass had a volume of 1 and you wanted an overlapping volume of 2). Infinite loops are a bad idea in all cases so you’ll need to write a bunch more code to prevent them, or risk having to force quit Revit periodically.

  2. You can have to do a bunch of compute with no value, as you may have to shift the elements many unknown number of times to get your first result.

  3. Transactions and document regeneration is slower than using geometry. Pulling the solids and working with them means you can commit one action (just find the first vector which produces the volume and move the element by that).

  4. Finding a ‘realistic’ value using a single calculation is doable. In most real cases you can move the two solids so they have an adjoining surface by using a pair of ‘closest point to’ methods to form a vector and shift the first object by that vector, divide the desired volume by the area of that overlapping surface to find the necessary depth, add the normal vector of the surface for the first object scaled to the depth value to the original vector. Shift the original first object by that vector and validate the results. This won’t work for highly irregular solids but those are quite rare.

2 Likes

I see, in my case the solids are irregular, therefore I was thinking to shift the moving element (or element1) iteratively.
The goal is to check whether the element2 (or observed element) fits in element1 and returns a textual or visual feedback.

In addition to that, this will be repeated because there are a list of observed elements to be checked.

So, would this be something that can be done with Finery/Revit Generative Design?

Generative Design might work well here - would need to see what types of irregularities you’re referring to in order to know what is best. There is no fast solution to the ‘knapsack’ problem at scale, but iteration is generally a bad direction to take.